00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00020 #include<ImLib3D/Image3D.hpp>
00021 #include<ImLib3D/TestPatterns.hpp>
00022 #include<ImLib3D/Display.hpp>
00023 #include<ImLib3D/ConvenienceProcessors.hpp>
00024 #include<stdexcept>
00025 #include <errno.h>
00026
00027 void
00028 XMLBinaryFile::Error(const char *fmt, ...)
00029 {
00030 static bool firstTime=true;
00031 va_list args;
00032 va_start(args,fmt);
00033 if(!fmt)
00034 {
00035 fprintf(stderr,"format string null\n");
00036 ThrowError("XMLBinaryFile::Error encountered null format string while already processing error!");
00037 }
00038 char msg[1000];
00039 char msg1[1000];
00040 vsprintf(msg,fmt,args);
00041 sprintf(msg1," :For file name:%s\n",fileName.c_str());
00042 strcat(msg,msg1);
00043 if(!firstTime){ThrowError(msg);}
00044 if(exceptionOnFail){throw runtime_error(msg);}
00045 firstTime=false;
00046 fprintf(stderr, "************ File Error ***********\n");
00047 fprintf(stderr, "************ Error Message : %s",msg);
00048 if(errno){perror("************ System Error :");}
00049 fprintf(stderr, "************ Dumping XMLTree:\n");
00050 ShowXML();
00051 ThrowError(msg);
00052 }
00053
00054 XMLBinaryFile::XMLBinaryFile(const string &_fileName,const string &mode,bool _exceptionOnFail):
00055 debug(0),
00056 fileName(_fileName),
00057 binaryFile(NULL),
00058 parser(NULL),
00059 document(NULL),
00060 binaryCurrentAllocPos(0),
00061 posInsideCurrentAllocBlock(0),
00062 currentAllocBlockSize(0),
00063 binaryBegining(0),
00064 isOpen(false),
00065 exceptionOnFail(_exceptionOnFail)
00066 {
00067 if(mode=="r"){OpenRead(fileName);}
00068 else
00069 if(mode=="w"){OpenWrite(fileName);}
00070 else
00071
00072 if(mode=="m"){isWrite=false;fileName="";document=new xmlpp::Document();}
00073 else
00074 {
00075 ThrowError("XMLBinaryFile::XMLBinaryFile unknow mode:\"%s\"",mode);
00076 }
00077 }
00078 void
00079 XMLBinaryFile::OpenRead(const string &_fileName)
00080 {
00081 isWrite=false;
00082 fileName=_fileName;
00083
00084 string header=ReadXMLHeader();
00085
00086 parser=new xmlpp::DomParser();
00087 parser->parse_memory(header);
00088 document=parser->get_document();
00089 if(debug){cout << "OpenRead:tree:" << endl;ShowXML();}
00090 binaryFile=fopen(fileName.c_str(),"r");
00091 if(!binaryFile){Error("XMLBinaryFile::OpenRead can't open:%s",fileName.c_str());}
00092 isOpen=true;
00093 }
00094 void
00095 XMLBinaryFile::OpenWrite(const string &_fileName)
00096 {
00097 isWrite=true;
00098 fileName=_fileName;
00099 binFileName=WriteTmpFile("empty");
00100 mprintf("binFileName:%s fileName:%s\n",binFileName.c_str(),fileName.c_str());
00101 binaryFile=fopen(binFileName.c_str(),"r+");
00102 if(!binaryFile){Error("XMLBinaryFile::OpenWrite can't open:%s",binFileName.c_str());}
00103 document=new xmlpp::Document();
00104 isOpen=true;
00105 }
00106 void
00107 XMLBinaryFile::Close()
00108 {
00109 if(isWrite)
00110 {
00111
00112 if(debug){cout << "Close:tree:" << endl;ShowXML();}
00113 document->write_to_file(fileName);
00114
00115 FILE *mainFile=fopen(fileName.c_str(),"a");
00116 if(!mainFile){Error("XMLBinaryFile::Close could not reopen mainFile:\"%s\"",fileName.c_str());}
00117 fprintf(mainFile,"::BeginBinary::\n");
00118 long binarySize=ftell(binaryFile);
00119 rewind(binaryFile);
00120 const size_t bufferSize=50*1000*1000;
00121 char *buffer=new char[bufferSize];
00122 for(size_t remaining=binarySize;remaining>0;)
00123 {
00124 size_t blockSize=min(remaining,bufferSize);
00125 if(fread(buffer,blockSize,1,binaryFile)!=1)
00126 {
00127 Error("XMLBinaryFile::Close failed while reading temporary binary file");
00128 }
00129 if(fwrite(buffer,blockSize,1,mainFile)!=1)
00130 {
00131 Error("XMLBinaryFile::Close failed while writing final binary file");
00132 }
00133 remaining-=blockSize;
00134 }
00135 delete [] buffer;
00136 if(fclose(binaryFile)){Error("XMLBinaryFile::Close failed while closing (read) temproary binary file");}
00137 binaryFile=NULL;
00138 if(fclose(mainFile)){Error("XMLBinaryFile::Close failed while closing (write) final binary file");}
00139
00140
00141 RemoveFile(binFileName);
00142 }
00143 else
00144 {
00145 fclose(binaryFile);
00146 binaryFile=NULL;
00147 }
00148 isOpen=false;
00149 }
00150
00151 xmlpp::Element *
00152 XMLBinaryFile::AddBinaryNode(xmlpp::Element *parent,int size)
00153 {
00154 if( posInsideCurrentAllocBlock <currentAllocBlockSize)
00155 {mprintf("WARNING: XMLBinaryFile::AddBinaryNode previous bin node did not fill up it's binary data");}
00156
00157 AllocInBinary(size);
00158 xmlpp::Element *dataN=parent->add_child("BinaryData");
00159 dataN->set_attribute("binoffset" ,SPrintf("%d",binaryCurrentAllocPos));
00160 dataN->set_attribute("binsize" ,SPrintf("%d",size));
00161
00162 if(debug)
00163 {
00164 mprintf("AddBinaryNode:: xxxxxxxxxxxxxxx created BinaryData xml node:\n");
00165 ShowXML(dataN);
00166 mprintf("AddBinaryNode:: xxxxxxxxxxxxxxx created BinaryData xml node from parent:\n");
00167 ShowXML(parent);
00168 mprintf("AddBinaryNode:: xxxxxxxxxxxxxxx from root:\n");
00169 string all=document->write_to_string();
00170 mprintf("%s\n",all.c_str());
00171 }
00172 return dataN;
00173 }
00174 void
00175 XMLBinaryFile::BinaryWrite(void *data,size_t size)
00176 {
00177 if(!binaryFile){Error("XMLBinaryFile::BinaryWrite binaryFile was not open");}
00178 if( posInsideCurrentAllocBlock+size >currentAllocBlockSize)
00179 {Error("XMLBinaryFile::BinaryWrite attempt to write past end of alloc block");}
00180
00181 posInsideCurrentAllocBlock+=size;
00182 if(fwrite(data,size,1,binaryFile)!=1)
00183 {
00184 Error("XMLBinaryFile::BinaryWrite failed while writing temp binary file");
00185 }
00186 }
00187 void
00188 XMLBinaryFile::BinaryWrite(xmlpp::Element *binNode,void *data,size_t size)
00189 {
00190 if(!binaryFile){Error("XMLBinaryFile::BinaryWrite binaryFile was not open");}
00191 if(fwrite(data,size,1,binaryFile)!=1)
00192 {
00193 Error("XMLBinaryFile::BinaryWrite failed while writing temp binary file");
00194 }
00195 posInsideCurrentAllocBlock+=size;
00196 }
00197 void
00198 XMLBinaryFile::EndBinaryWrite(xmlpp::Element *binNode)
00199 {
00200 xmlpp::Attribute *attribute=binNode->get_attribute("binsize");
00201 if(!attribute){Error("XMLBinaryFile::EndBinaryWrite no binsize in binNode ");}
00202 if(currentAllocBlockSize==0){currentAllocBlockSize=posInsideCurrentAllocBlock;}
00203 attribute->set_value(SPrintf("%d",currentAllocBlockSize));
00204 }
00205 void
00206 XMLBinaryFile::ReadBinaryNode(xmlpp::Element *parent)
00207 {
00208 xmlpp::Element::NodeList nodeList;
00209 if((nodeList=parent->get_children("BinaryData")).size()!=1)
00210 {Error("XMLBinaryFile::ReadBinaryNode: no binary data child node in xml node");}
00211 xmlpp::Element *dataN=dynamic_cast<xmlpp::Element*>(*nodeList.begin());
00212
00213 binaryCurrentAllocPos = LongInt(dataN->get_attribute("binoffset" )->get_value());
00214 currentAllocBlockSize = LongInt(dataN->get_attribute("binsize" )->get_value());
00215 posInsideCurrentAllocBlock=0;
00216
00217 fseek(binaryFile,binaryCurrentAllocPos+binaryBegining,SEEK_SET);
00218 }
00219
00220 void
00221 XMLBinaryFile::BinaryRead(void *data,size_t size)
00222 {
00223 if(!binaryFile){Error("XMLBinaryFile::BinaryRead binaryFile was not open");}
00224
00225 if( posInsideCurrentAllocBlock+size >currentAllocBlockSize)
00226 {Error("XMLBinaryFile::BinaryRead attempt to read past end of alloc block");}
00227 posInsideCurrentAllocBlock+=size;
00228 if(fread(data,size,1,binaryFile)!=1)
00229 {
00230 Error("XMLBinaryFile::BinaryRead error reading");
00231 }
00232 }
00233 bool
00234 XMLBinaryFile::CheckBinaryReadComplete()
00235 {
00236 return posInsideCurrentAllocBlock==currentAllocBlockSize;
00237 }
00238
00239 int
00240 XMLBinaryFile::AllocInBinary(size_t size)
00241 {
00242 binaryCurrentAllocPos+=currentAllocBlockSize;
00243 currentAllocBlockSize=size;
00244 posInsideCurrentAllocBlock=0;
00245 if(binaryFile)
00246 {
00247 fseek(binaryFile,binaryCurrentAllocPos,SEEK_SET);
00248 }
00249 return binaryCurrentAllocPos;
00250 }
00251
00252 string
00253 XMLBinaryFile::ReadXMLHeader()
00254 {
00255
00256
00257 FILE *F=fopen(fileName.c_str(),"r");
00258 if(!F)
00259 {
00260 Error("XMLBinaryFile::ReadXMLHeader: Open file failed : filename:\"%s\"",fileName.c_str());
00261 }
00262 char buff[10000];
00263
00264
00265
00266 int headerSize;
00267 for(;;)
00268 {
00269 int pos=ftell(F);
00270 char *cline=fgets(buff,10000,F);
00271 if(!cline){Error("XMLBinaryFile::ReadXMLHeader: bad file could not find:\"</ImLib3DFileDescription>\"");}
00272 string line=cline;
00273
00274 if(line==SPrintf("::BeginBinary::\n"))
00275 {
00276 headerSize=pos;
00277 binaryBegining=ftell(F);
00278 break;
00279 }
00280
00281
00282 if(line.find("</ImLib3DFileDescription>")!=line.npos)
00283 {
00284 headerSize=ftell(F);
00285 binaryBegining=ftell(F);
00286
00287 string nline=fgets(buff,10000,F);
00288 if(nline!=SPrintf("::BeginBinary::\n"))
00289 {
00290 break;
00291 }
00292 binaryBegining=ftell(F);
00293 break;
00294 }
00295 }
00296
00297
00298 fseek(F,0,SEEK_SET);
00299 char *cheader=new char[headerSize+1];
00300 fread(cheader,headerSize,1,F);
00301 cheader[headerSize]='\0';
00302 if(debug){mprintf("cheader:\"%s\"\n",cheader);}
00303 string header=cheader;
00304 delete [] cheader;
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 fclose(F);
00316 return header;
00317 }
00318
00319 void
00320 XMLBinaryFile::ShowXML(xmlpp::Element *node,int depth)
00321 {
00322 if(!node)
00323 {
00324 mprintf("ShowXML from root for:%s:\n",fileName.c_str());
00325 node=document->get_root_node();
00326 }
00327 if(!node){mprintf("WARNING:ShowXML no xml tree yet\n");return;}
00328 int nspaces=depth*4;
00329 char *spaces=new char[nspaces+1];
00330 for(int ll=0;ll<nspaces;ll++)spaces[ll]=' ';
00331 spaces[nspaces]=0;
00332
00333
00334 mprintf("%sNODE:\"%s\" children:",spaces,node->get_name().c_str());
00335
00336 vector<xmlpp::Element *> children=ChildElements(node);
00337 for(vector<xmlpp::Element *>::iterator p=children.begin();p!=children.end();++p)
00338 {
00339 mprintf("%s,",(*p)->get_name().c_str());
00340 }
00341 mprintf("\n");
00342 xmlpp::Element::AttributeList attributes=node->get_attributes();
00343 xmlpp::Element::AttributeList::iterator ip;
00344
00345 mprintf("%snode attributes:",spaces);
00346 if(attributes.size()==0){mprintf("(none)");}
00347 for(ip=attributes.begin();ip!=attributes.end();++ip)
00348 {
00349 mprintf("%s:%s , ",(*ip)->get_name().c_str(),(*ip)->get_value().c_str());
00350 }
00351 mprintf("\n");
00352 for(vector<xmlpp::Element *>::iterator p=children.begin();p!=children.end();++p)
00353 {
00354 ShowXML(*p,depth+1);
00355 }
00356 delete [] spaces;
00357 }
00358
00359
00360 xmlpp::Element *
00361 XMLBinaryFile::GetRoot(const string &rootName)
00362 {
00363 xmlpp::Element *root=document->get_root_node();
00364 if(!root){Error("XMLBinaryFile::GetRoot (\"%s\" ) no root!\n",rootName.c_str());}
00365 if(rootName!="" && root->get_name()!=rootName){Error("XMLBinaryFile::GetRoot (\"%s\" ) names dont match:\"%s\"\n",
00366 rootName.c_str(),root->get_name().c_str());}
00367 return root;
00368 }
00369
00370 xmlpp::Element *
00371 XMLBinaryFile::AddChild(xmlpp::Element *parent,const string &name,const string &a1,const string &a2,const string &a3,const string &a4)
00372 {
00373 vector<string> args=Strings(a1,a2,a3,a4);
00374 xmlpp::Element *child=parent->add_child(name);
00375 for(uint i=0;i<args.size();i+=2)
00376 {
00377 if (args[i] =="")continue;
00378 child->set_attribute(args[i],args[i+1]);
00379 }
00380 return child;
00381 }
00382
00383 bool
00384 XMLBinaryFile::HasChild(xmlpp::Element *parent,const string &name)
00385 {
00386 xmlpp::Element::NodeList nodeList=parent->get_children(name);
00387 return nodeList.size()!=0;
00388 }
00389 xmlpp::Element *
00390 XMLBinaryFile::GetChild(xmlpp::Element *parent,const string &name)
00391 {
00392 xmlpp::Element::NodeList nodeList=parent->get_children(name);
00393 int n=nodeList.size();
00394 if(n>1){Error("XMLBinaryFile::GetChild: found more than one child:\"%s\":%d",name.c_str(),n);}
00395 if(!n ){Error("XMLBinaryFile::GetChild: could not find child:\"%s\"",name.c_str());}
00396 xmlpp::Element *child=dynamic_cast<xmlpp::Element*>(*nodeList.begin());
00397 return child;
00398 }
00399 string
00400 XMLBinaryFile::GetAttribute (xmlpp::Element *node,const string &name)
00401 {
00402 if(!node)
00403 {
00404 Error("XMLBinaryFile::GetAttribute(%s): node==NULL!\n",name.c_str());
00405 }
00406 xmlpp::Attribute *attribute=node->get_attribute(name);
00407 if(!attribute)
00408 {
00409 Error("XMLBinaryFile::GetAttribute attribute \"%s\" of node \"%s\" not found",
00410 name.c_str(),node->get_name().c_str());
00411 }
00412
00413 return attribute->get_value();
00414 }
00415 bool
00416 XMLBinaryFile::HasAttribute (xmlpp::Element *node,const string &name)
00417 {
00418 return node->get_attribute(name)!=NULL;
00419 }
00420 string
00421 XMLBinaryFile::Quote(const string &src)
00422 {
00423 string res=src;
00424 Replace(res,"\n","\\n");
00425 return res;
00426 }
00427 string
00428 XMLBinaryFile::UnQuote(const string &src)
00429 {
00430 string res=src;
00431 Replace(res,"\\n","\n");
00432 return res;
00433 }