Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

XMLBinaryFile.cpp

Go to the documentation of this file.
00001 /* ImLib3D
00002  * Copyright (c) 2001, ULP-IPB Strasbourg.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or (at
00007  * your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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     // in memory dud file 
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     // read the xml header from the image file
00084     string header=ReadXMLHeader();
00085     // parse xml header into xml tree
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         // ******** write xml tree into file
00112         if(debug){cout << "Close:tree:" << endl;ShowXML();}
00113         document->write_to_file(fileName);
00114         // ********  now append  the binary file to the xml header
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 //          system(SPrintf("cat %s >> %s",binFileName,fileName).c_str());
00140         // cleanup temporary binary file
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 //      mprintf("BinaryWrite: %x: at:%d size:%d\n",data,posInsideCurrentAllocBlock,size);
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 //      mprintf("BinaryRead: %x: at:%d size:%d (block size:%d)\n",data,posInsideCurrentAllocBlock,size,currentAllocBlockSize);
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 //          int filesize=FileSize(fileName);
00256     // open the file
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     // look for the the end of the xml/ begining of binary
00264     // end is defined by either ::BeginBinary::
00265     // or just ("</ImLib3DFileDescription>")
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         {// found end of header
00276             headerSize=pos;
00277             binaryBegining=ftell(F);
00278             break;
00279         }
00280 
00281         // support for deprecated "</ImLib3DFileDescription>" without "::BeginBinary::"
00282         if(line.find("</ImLib3DFileDescription>")!=line.npos)
00283         {
00284             headerSize=ftell(F);
00285             binaryBegining=ftell(F);
00286             // read ahead one line to see if there is a "::BeginBinary::"
00287             string nline=fgets(buff,10000,F);
00288             if(nline!=SPrintf("::BeginBinary::\n"))
00289             {// argh no "::BeginBinary:: deprecated!
00290                 break;
00291             }
00292             binaryBegining=ftell(F);
00293             break;
00294         }
00295     }
00296 //      mprintf("headerSize:%d binaryBegining:%d\n",headerSize,binaryBegining);
00297     // re-read the header into a string
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 //  // test
00307 //          int binsize=filesize-header.size();
00308 //          fseek(F,header.size(),SEEK_SET);
00309 //          char binb[10000];
00310 //          fread(binb,binsize,1,F);
00311 //          binb[binsize]=0;
00312 //          mprintf("readbin:%s\n",binb);
00313 
00314         // close file
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 //      cout << "node:" << node->get_name() << " : " << node->get_children().size() << " children" <<  endl;
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 }

Generated on Fri Jun 17 13:36:10 2005 for ImLib3D by  doxygen 1.4.2