Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/wroot/file is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_wroot_file
0005 #define tools_wroot_file
0006 
0007 #include "ifile"
0008 
0009 #include "directory"
0010 
0011 #include "infos"
0012 #include "free_seg"
0013 
0014 #include "../platform"
0015 
0016 #include "../path"
0017 
0018 #include <map>
0019 
0020 #include <fcntl.h>
0021 #include <errno.h>
0022 #include <sys/stat.h>
0023 
0024 #if defined(_MSC_VER) || defined(__MINGW32__)
0025 #include <direct.h>
0026 #include <io.h>
0027 #else
0028 #include <unistd.h>
0029 #endif
0030 
0031 namespace tools {
0032 namespace wroot {
0033 
0034 class file : public virtual ifile {
0035   file& get_me() {return *this;} //_MSC_VER : to avoid warning about the usage of "this" in the constructor.
0036   static int not_open() {return -1;}
0037   static uint32 kBegin() {return 64;}
0038 public:
0039   static const std::string& s_class() {
0040     static const std::string s_v("tools::wroot::file");
0041     return s_v;
0042   }
0043   virtual const std::string& s_cls() const {return s_class();}
0044 public: //ifile
0045   virtual bool verbose() const {return m_verbose;}
0046   virtual std::ostream& out() const {return m_out;}
0047 
0048   virtual bool byte_swap() const {return is_little_endian();}
0049   virtual bool set_pos(seek a_offset = 0,from a_from = begin){
0050     int whence = 0;
0051     switch(a_from) {
0052     case begin:
0053       whence = SEEK_SET;
0054       break;
0055     case current:
0056       whence = SEEK_CUR;
0057       break;
0058     case end:
0059       whence = SEEK_END;
0060       break;
0061     }
0062 
0063 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
0064     if (::lseek64(m_file, a_offset, whence) < 0) {
0065 #elif defined(_MSC_VER) || defined(__MINGW32__)
0066     if (::_lseeki64(m_file, a_offset, whence) < 0) {
0067 #else
0068     if (::lseek(m_file, a_offset, whence) < 0) {
0069 #endif
0070       m_out << "tools::wroot::file::set_pos :"
0071             << " cannot set position " << a_offset
0072             << " in file " << sout(m_path) << "."
0073             << std::endl;
0074       return false;
0075     }
0076     return true;
0077   }
0078 
0079   virtual seek END() const {return m_END;}
0080   virtual void set_END(seek a_end){
0081     m_END = a_end;
0082 
0083     if(m_free_segs.empty()) {
0084       m_out << "tools::wroot::file::set_END :"
0085             << " free_seg list should not be empty here."
0086             << std::endl;
0087     } else {
0088       free_seg* end_seg = m_free_segs.back();
0089       if(end_seg->last()!=START_BIG_FILE()) {
0090         m_out << "tools::wroot::file::set_END :"
0091               << " last free_seg is not the ending of file one."
0092               << " free_seg list looks corrupted."
0093               << std::endl;
0094       } else {
0095         m_free_segs.back()->set_first(m_END);
0096       }
0097     }
0098   }
0099 
0100   virtual bool write_buffer(const char* a_buffer,uint32 a_length) {
0101     // Write a buffer to the file. This is the basic low level write operation.
0102 #ifdef _MSC_VER
0103     typedef int ssize_t;
0104 #endif
0105     ssize_t siz;
0106     while ((siz = ::write(m_file,a_buffer,a_length)) < 0 &&
0107             error_number() == EINTR) reset_error_number();
0108 
0109     if(siz < 0) {
0110       m_out << "tools::wroot::file::write_buffer :"
0111             << " error writing to file " << sout(m_path) << "."
0112             << std::endl;
0113       return false;
0114     }
0115     if(siz!=(ssize_t)a_length) {
0116       m_out << "tools::wroot::file::write_buffer :"
0117            << "error writing all requested bytes to file " << sout(m_path)
0118            << ", wrote " << long_out(siz) << " of " << a_length
0119            << std::endl;
0120       return false;
0121     }
0122     //m_bytes_write  += siz;
0123     return true;
0124   }
0125 
0126   virtual uint32 version() const {
0127     // Return version id as an integer, i.e. "2.22/04" -> 22204.
0128     static const uint32 ROOT_MAJOR_VERSION = 4;
0129     static const uint32 ROOT_MINOR_VERSION = 0;
0130     static const uint32 ROOT_PATCH_VERSION = 0;
0131     return
0132       10000 * ROOT_MAJOR_VERSION +
0133       100 * ROOT_MINOR_VERSION +
0134       ROOT_PATCH_VERSION;
0135   }
0136 
0137   virtual bool synchronize(){
0138     // Synchornize a file's in-core and on-disk states.
0139 #ifdef _MSC_VER
0140     if(::_commit(m_file)) {
0141       m_out << "tools::wroot::file::synchronize :"
0142             << " in _commit() for file " << sout(m_path) << "."
0143             << std::endl;
0144       return false;
0145     }
0146 #elif defined(__MINGW32__)
0147     return true;
0148 #else
0149     if (::fsync(m_file) < 0) {
0150       m_out << "tools::wroot::file::synchronize :"
0151             << " error in fsync() for file " << sout(m_path) << "."
0152             << std::endl;
0153       return false;
0154     }
0155 #endif
0156     return true;
0157   }
0158 
0159   virtual bool ziper(char a_key,compress_func& a_func) const {
0160     std::map<char,compress_func>::const_iterator it = m_zipers.find(a_key);
0161     if(it==m_zipers.end()) {
0162       a_func = 0;
0163       return false;
0164     }
0165     a_func = (*it).second;
0166     return true;
0167   }
0168   virtual uint32 compression() const {return m_compress;}
0169   virtual void compress_buffer(const buffer& a_buffer,char*& a_kbuf,uint32& a_klen,bool& a_kdel) {
0170     //NOTE : if(kdelete) delete [] kbuf;
0171 
0172     a_kbuf = 0;
0173     a_klen = 0;
0174     a_kdel = false;
0175 
0176     uint32 nbytes = a_buffer.length();
0177     uint32 cxlevel = m_compress;
0178     if(cxlevel && (nbytes>256)) {
0179       compress_func func;
0180       if(!ziper('Z',func)) {
0181         //m_out << "tools::wroot::directory::write_object :"
0182         //      << " zlib ziper not found."
0183         //      << std::endl;
0184         a_kbuf = (char*)a_buffer.buf();
0185         a_klen = a_buffer.length();
0186         a_kdel = false;
0187       } else {
0188         const uint32 kMAXBUF = 0xffffff;
0189         const uint32 HDRSIZE = 9;
0190         uint32 nbuffers = nbytes/kMAXBUF;
0191         uint32 buflen = nbytes+HDRSIZE*(nbuffers+1);
0192         a_kbuf = new char[buflen];
0193         a_kdel = true;
0194         char* src = (char*)a_buffer.buf();
0195         char* tgt = a_kbuf;
0196         uint32 nzip = 0;
0197         for(uint32 i=0;i<=nbuffers;i++) {
0198           uint32 bufmax = ((i == nbuffers) ? nbytes - nzip : kMAXBUF);
0199           uint32 nout;
0200           if(!zip(m_out,func,cxlevel,bufmax,src,bufmax,tgt,nout)) {
0201             delete [] a_kbuf;
0202             a_kbuf = (char*)a_buffer.buf();
0203             a_klen = a_buffer.length();
0204             a_kdel = false;
0205             break;
0206           }
0207           tgt += nout; //nout includes HDRSIZE
0208           a_klen += nout;
0209           src += kMAXBUF;
0210           nzip += kMAXBUF;
0211         }
0212         //::printf("debug : compress : end : %u %u\n",nbytes,klen);
0213       }
0214     } else {
0215       a_kbuf = (char*)a_buffer.buf();
0216       a_klen = a_buffer.length();
0217       a_kdel = false;
0218     }
0219   }
0220 public:
0221   file(std::ostream& a_out,const std::string& a_path,bool a_verbose = false)
0222   :m_out(a_out)
0223   ,m_path(a_path)
0224   ,m_verbose(a_verbose)
0225   ,m_file(not_open())
0226   //,m_bytes_write(0)
0227   ,m_root_directory(get_me(),nosuffix(a_path),m_title)
0228   // begin of record :
0229   ,m_version(0)
0230   ,m_BEGIN(0)
0231   ,m_END(0)
0232   ,m_seek_free(0)
0233   ,m_nbytes_free(0)
0234   ,m_nbytes_name(0)
0235   ,m_units(4)
0236   ,m_compress(1)
0237   ,m_seek_info(0)
0238   ,m_nbytes_info(0)
0239   {
0240 #ifdef TOOLS_MEM
0241     mem::increment(s_class().c_str());
0242 #endif
0243 
0244     m_version = version();
0245 
0246     if(access_path(m_path,kFileExists)) unlink(m_path);
0247 
0248     if(!m_root_directory.is_valid()) {
0249       m_out << "tools::wroot::file::file :"
0250             << " " << sout(m_path) << " root directory badly created."
0251             << std::endl;
0252       return;
0253     }
0254 
0255     m_file = _open(a_path.c_str(),
0256 #if defined(_MSC_VER) || defined(__MINGW32__)
0257                                O_RDWR | O_CREAT | O_BINARY,S_IREAD | S_IWRITE
0258 #else
0259                                O_RDWR | O_CREAT,0644
0260 #endif
0261     );
0262     if(m_file==not_open()) {
0263       m_out << "tools::wroot::file::file :"
0264             << " can't open " << sout(a_path) << "."
0265             << std::endl;
0266       return;
0267     }
0268 
0269     //initialize :
0270 
0271     m_BEGIN = kBegin();  // First used word in file following the file header.
0272     m_END = m_BEGIN;   // Pointer to end of file.
0273 
0274     m_free_segs.push_back(new free_seg(m_out,m_BEGIN,START_BIG_FILE()));
0275 
0276     // Write Directory info :
0277     uint32 namelen =
0278       key::std_string_record_size(m_path) +
0279       key::std_string_record_size(m_title);
0280     uint32 nbytes = namelen + m_root_directory.record_size();
0281 
0282     //TUUID version 1:
0283     nbytes += sizeof(unsigned int);
0284     nbytes += 2*sizeof(unsigned short);
0285     nbytes += 8*sizeof(unsigned char);
0286 
0287     wroot::key key(m_out,*this,0,m_path,m_title,"TFile",nbytes); // It does a (*this).set_END().
0288 
0289     // m_nbytes_name = start point of directory info from key head.
0290     m_nbytes_name = key.key_length() + namelen;
0291     m_root_directory.set_nbytes_name(m_nbytes_name);
0292     m_root_directory.set_seek_directory(key.seek_key()); //at EOF.
0293 
0294     //the below write 45 bytes at BOF (Begin Of File).
0295     if(!write_header()) { //need m_nbytes_name, m_END after key written.
0296       m_out << "tools::wroot::file::file :"
0297             << " can't write file header."
0298             << std::endl;
0299       return;
0300     }
0301 
0302    {char* pos = key.data_buffer();
0303     wbuf wb(m_out,byte_swap(),key.eob(),pos);
0304     if(!wb.write(m_path)) return;
0305     if(!wb.write(m_title)) return;
0306     if(!m_root_directory.to_buffer(wb)) return;
0307     //TUUID version 1:
0308     if(!wb.write((unsigned int)0)) return;
0309     if(!wb.write((unsigned short)0)) return;
0310     if(!wb.write((unsigned short)0)) return;
0311    {for(size_t count=0;count<8;count++) if(!wb.write((unsigned char)0)) return;}}
0312 
0313     if(m_verbose) {
0314       m_out << "tools::wroot::file::file :"
0315             << " write key ("
0316             << namelen
0317             << ", "
0318             << m_root_directory.record_size()
0319             << ", "
0320             << nbytes
0321             << ", "
0322             << m_nbytes_name
0323             << ", "
0324             << key.seek_key()
0325             << ")."
0326             << std::endl;
0327     }
0328 
0329     key.set_cycle(1);
0330     if(!key.write_self(*this)) {
0331       m_out << "tools::wroot::file::file :"
0332             << " key.write_self() failed."
0333             << std::endl;
0334       return;
0335     }
0336 
0337     //the below write at kBegin + nbytes.
0338     //64+52
0339     uint32 n;
0340     if(!key.write_file(*this,n)) {
0341       m_out << "tools::wroot::file::file :"
0342             << " can't write key in file."
0343             << std::endl;
0344       return;
0345     }
0346     //::printf("debug : file::file : write key : %d\n",n);
0347 
0348   }
0349   virtual ~file() {
0350     close();
0351 #ifdef TOOLS_MEM
0352     mem::decrement(s_class().c_str());
0353 #endif
0354   }
0355 protected:
0356   file(const file& a_from)
0357   :ifile(a_from)
0358   ,m_out(a_from.m_out)
0359   ,m_root_directory(get_me())
0360   {
0361 #ifdef TOOLS_MEM
0362     mem::increment(s_class().c_str());
0363 #endif
0364   }
0365   file& operator=(const file&){return *this;}
0366 public:
0367   const std::string& path() const {return m_path;}
0368 
0369   void set_compression(uint32 a_level) {
0370     // level = 0 objects written to this file will not be compressed.
0371     // level = 1 minimal compression level but fast.
0372     // ....
0373     // level = 9 maximal compression level but slow.
0374     m_compress = a_level;
0375     if(m_compress>9) m_compress = 9;
0376   }
0377 
0378   bool is_open() const {return (m_file==not_open()?false:true);}
0379 
0380   void close() {
0381     if(m_file==not_open()) return;
0382     m_root_directory.close();
0383 
0384     if(m_free_segs.size()) {
0385       if(!write_free_segments()) {
0386         m_out << "tools::wroot::file::close :"
0387               << " can't write free segments."
0388               << std::endl;
0389       }
0390       if(!write_header())  { // Now write file header
0391         m_out << "tools::wroot::file::close :"
0392               << " can't write file header."
0393               << std::endl;
0394       }
0395     }
0396 
0397    {std::list<free_seg*>::iterator it;
0398     for(it=m_free_segs.begin();
0399         it!=m_free_segs.end();
0400         it = m_free_segs.erase(it)) {
0401       delete (*it);
0402     }}
0403 
0404     ::close(m_file);
0405     m_file = not_open();
0406   }
0407 
0408   directory& dir() {return m_root_directory;}
0409   const directory& dir() const {return m_root_directory;}
0410 
0411   bool write(uint32& a_nbytes){
0412     // Write memory objects to this file :
0413     //  Loop on all objects in m_root_directory (including subdirectories).
0414     //  A new key is created in the directories m_keys linked list
0415     //  for each object.
0416     //  The list of keys is then saved on the file (via write_keys)
0417     //  as a single data record.
0418     //  The directory header info is rewritten on the directory header record.
0419     //  //The linked list of FREE segments is written.
0420     //  The file header is written (bytes 1->m_BEGIN).
0421     a_nbytes = 0;
0422 
0423     if(m_verbose) {
0424       m_out << "tools::wroot::file::write :"
0425             << " writing Name=" << sout(m_path)
0426             << " Title=" << sout(m_title) << "."
0427             << std::endl;
0428     }
0429 
0430     uint32 nbytes;
0431     if(!m_root_directory.write(nbytes)) return false; // Write directory tree
0432 
0433     if(!write_streamer_infos()) {
0434       m_out << "tools::wroot::file::write :"
0435             << " write_streamer_infos failed."
0436             << std::endl;
0437       return false;
0438     }
0439 
0440     if(!write_free_segments()) {
0441       m_out << "tools::wroot::file::write :"
0442             << " can't write free segments."
0443             << std::endl;
0444       return false;
0445     }
0446 
0447     if(!write_header()) { //write 45 bytes at BOF.
0448       m_out << "tools::wroot::file::write :"
0449             << " can't write file header."
0450             << std::endl;
0451       return false;
0452     }
0453 
0454     a_nbytes = nbytes;
0455     return true;
0456   }
0457 
0458   bool add_ziper(char a_key,compress_func a_func){
0459     std::map<char,compress_func>::const_iterator it = m_zipers.find(a_key);
0460     if(it!=m_zipers.end()) {
0461       //(*it).second = a_func; //override ?
0462       return false;
0463     } else {
0464       m_zipers[a_key] = a_func;
0465       return true;
0466     }
0467   }
0468 protected:
0469   enum EAccessMode {
0470     kFileExists        = 0,
0471     kExecutePermission = 1,
0472     kWritePermission   = 2,
0473     kReadPermission    = 4
0474   };
0475   static bool access_path(const std::string& a_path,EAccessMode a_mode){
0476     // Returns true if one can access a file using the specified access mode.
0477     // Mode is the same as for the WinNT access(2) function.
0478 #ifdef _MSC_VER
0479     return (::_access(a_path.c_str(),a_mode) == 0) ? true : false;
0480 #else
0481     return (::access(a_path.c_str(),a_mode) == 0) ? true : false;
0482 #endif
0483   }
0484   static bool unlink(const std::string& a_path){
0485     // Unlink, i.e. remove, a file or directory. Returns true when succesfull,
0486     // false in case of failure.
0487     struct stat finfo;
0488     if (::stat(a_path.c_str(),&finfo) < 0) return false;
0489 #ifdef _MSC_VER
0490     if (finfo.st_mode & S_IFDIR)
0491       return (::_rmdir(a_path.c_str())==-1 ? false : true);
0492     else
0493       return (::unlink(a_path.c_str())==-1 ? false : true);
0494 #else
0495     if (S_ISDIR(finfo.st_mode))
0496       return (::rmdir(a_path.c_str())==-1 ? false : true);
0497     else
0498       return (::unlink(a_path.c_str())==-1 ? false : true);
0499 #endif
0500   }
0501 
0502   static int _open(const char* a_name,int a_flags,unsigned int a_mode) {
0503 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
0504      return ::open64(a_name,a_flags,a_mode);
0505 #else
0506      return ::open(a_name,a_flags,a_mode);
0507 #endif
0508   }
0509   bool write_header() {
0510     const char root[] = "root";
0511     //char psave[kBegin()];
0512     char psave[128];
0513     const char* eob = psave + kBegin();
0514     char* pos = psave;
0515     ::memcpy(pos,root,4); pos += 4;
0516     uint32 vers = m_version;
0517     if((m_END>START_BIG_FILE())        ||
0518        (m_seek_free>START_BIG_FILE())  ||
0519        (m_seek_info>START_BIG_FILE())  ){
0520       vers += 1000000;
0521       m_units = 8;
0522     }
0523     wbuf wb(m_out,byte_swap(),eob,pos);
0524     if(!wb.write(vers)) return false;
0525     if(!wb.write((seek32)m_BEGIN)) return false;
0526     if(vers>1000000) {
0527       if(!wb.write(m_END)) return false;
0528       if(!wb.write(m_seek_free)) return false;
0529     } else {
0530       if(!wb.write((seek32)m_END)) return false;
0531       if(!wb.write((seek32)m_seek_free)) return false;
0532     }
0533     if(!wb.write(m_nbytes_free)) return false;
0534     //int nfree  = fFreeSegments.size();
0535     uint32 nfree  = 0; //FIXME
0536     if(!wb.write(nfree)) return false;
0537     if(!wb.write(m_nbytes_name)) return false;
0538     if(!wb.write(m_units)) return false;
0539     if(!wb.write(m_compress)) return false;
0540     if(vers>1000000) {
0541       if(!wb.write(m_seek_info)) return false;
0542     } else {
0543       if(!wb.write((seek32)m_seek_info)) return false;
0544     }
0545     if(!wb.write(m_nbytes_info)) return false;
0546     if(!set_pos()) return false; //BOF
0547     uint32 nbytes = uint32(pos - psave);
0548     //::printf("debug : write_header : %d\n",nbytes);
0549     if(!write_buffer(psave,nbytes)) return false;
0550     if(!synchronize()) return false;
0551     return true;
0552   }
0553 
0554   bool write_streamer_infos() {
0555     obj_list<streamer_info> sinfos;
0556     fill_infos(sinfos,m_out);
0557 
0558     if(sinfos.empty()) return false;
0559 
0560     buffer bref(m_out,byte_swap(),256);
0561 
0562     if(!sinfos.stream(bref)) {
0563       m_out << "tools::wroot::file::write_streamer_infos :"
0564             << " cannot stream obj_list<streamer_info>."
0565             << std::endl;
0566       return false;
0567     }
0568     uint32 nbytes = bref.length();
0569 
0570     wroot::key key(m_out,*this,
0571                    m_root_directory.seek_directory(),
0572                    "StreamerInfo","",
0573                    sinfos.store_cls(),
0574                    nbytes); // It does a (*this).set_END().
0575     if(!key.seek_key()) return false;
0576 
0577     if(!bref.displace_mapped(key.key_length())) return false;
0578 
0579     ::memcpy(key.data_buffer(),bref.buf(),nbytes);
0580 
0581     //key.set_cycle(1);
0582     if(!key.write_self(*this)) {
0583       m_out << "tools::wroot::file::write_streamer_infos :"
0584             << " key.write_self() failed."
0585             << std::endl;
0586       return false;
0587     }
0588 
0589     m_seek_info = key.seek_key();
0590     m_nbytes_info = key.number_of_bytes();
0591     //FIXME sumBuffer(key.objectSize());
0592 
0593     uint32 n;
0594     if(!key.write_file(*this,n)) return false;
0595     if(!n) return false;
0596 
0597     return true;
0598   }
0599 
0600   bool make_free_seg(seek a_first,seek a_last) {
0601     // Mark unused bytes on the file :
0602     //  The list of free segments is in the m_free_segs list
0603     //  When an object is deleted from the file, the freed space is added
0604     //  into the FREE linked list (m_free_segs). The FREE list consists
0605     //  of a chain  of consecutive free segments on the file. At the same
0606     //  time, the first 4 bytes of the freed record on the file
0607     //  are overwritten by GAPSIZE where
0608     //    GAPSIZE = -(Number of bytes occupied by the record).
0609 
0610     if(m_free_segs.empty()) {
0611       m_out << "tools::wroot::file::make_free_seg :"
0612             << " free_seg list should not be empty here."
0613             << std::endl;
0614       return false;
0615     }
0616 
0617     free_seg* newfree = add_free(m_free_segs,a_first,a_last);
0618     if(!newfree) {
0619       m_out << "tools::wroot::file::make_free_seg :"
0620             << " add_free failed."
0621             << std::endl;
0622       return false;
0623     }
0624 
0625     seek nfirst = newfree->first();
0626     seek nlast = newfree->last();
0627 
0628     seek _nbytes = nlast-nfirst+1;
0629     if(_nbytes>START_BIG_FILE()) _nbytes = START_BIG_FILE();
0630     int nbytes = -int(_nbytes);
0631 
0632     int nb = sizeof(int);
0633 
0634     char psave[128];
0635     const char* eob = psave + nb;
0636     char* pos = psave;
0637 
0638     wbuf wb(m_out,byte_swap(),eob,pos);
0639     if(!wb.write(nbytes)) return false;
0640 
0641     if(nlast == (m_END-1)) m_END = nfirst;
0642     if(!set_pos(nfirst)) return false;
0643     if(!write_buffer(psave,nb)) return false;
0644     if(!synchronize()) return false;
0645     return true;
0646   }
0647 
0648   bool write_free_segments(){
0649     //  The linked list of FREE segments (fFree) is written as a single data record.
0650 
0651     // Delete old record if it exists :
0652     if(m_seek_free){
0653       if(!make_free_seg(m_seek_free, m_seek_free + m_nbytes_free -1)) {
0654         m_out << "tools::wroot::file::write_free_segments :"
0655               << " key.write_self() failed."
0656               << std::endl;
0657         return false;
0658       }
0659     }
0660 
0661     //::printf("debug : write_free_segments : seg list :\n");
0662 
0663     uint32 nbytes = 0;
0664    {tools_lforcit(free_seg*,m_free_segs,it) {
0665       nbytes += (*it)->record_size();
0666       //::printf("debug : write_free_segments : %lu %lu\n",
0667       //         (*it)->first(),(*it)->last());
0668     }}
0669     if(!nbytes) return true;
0670 
0671     wroot::key key(m_out,*this,
0672                    m_root_directory.seek_directory(),
0673                    m_path,m_title,"TFile",
0674                    nbytes); // It does a (*this).set_END().
0675     if(!key.seek_key()) return false;
0676 
0677    {char* pos = key.data_buffer();
0678     wbuf wb(m_out,byte_swap(),key.eob(),pos);
0679     tools_lforcit(free_seg*,m_free_segs,it) {
0680       if(!(*it)->fill_buffer(wb)) return false;
0681     }}
0682 
0683     //key.set_cycle(1);
0684     if(!key.write_self(*this)) {
0685       m_out << "tools::wroot::file::write_free_segments :"
0686             << " key.write_self() failed."
0687             << std::endl;
0688       return false;
0689     }
0690 
0691     m_seek_free = key.seek_key();
0692     m_nbytes_free = key.number_of_bytes();
0693     if(m_verbose) {
0694       m_out << "tools::wroot::file::write_free_segments :"
0695             << " write key." << std::endl;
0696     }
0697 
0698     uint32 n;
0699     if(!key.write_file(*this,n)) return false;
0700     if(!n) return false;
0701 
0702     return true;
0703   }
0704 
0705   static bool zip(std::ostream& a_out,
0706                   compress_func a_func,
0707                   int a_level,
0708                   uint32 a_srcsize,char* a_src,
0709                   uint32 a_tgtsize,char* a_tgt,
0710                   uint32& a_irep){
0711 
0712     // from Rio/Bits/R__zip using zlib.
0713 
0714     const uint32 HDRSIZE = 9;
0715 
0716     if(a_tgtsize<HDRSIZE) {
0717       a_out << "tools::wroot::directory::zip :"
0718             << " target buffer too small."
0719             << std::endl;
0720       a_irep = 0;
0721       return false;
0722     }
0723     if(a_srcsize>0xffffff) {
0724       a_out << "tools::wroot::directory::zip :"
0725             << " source buffer too big."
0726             << std::endl;
0727       a_irep = 0;
0728       return false;
0729     }
0730 
0731     uint32 out_size;
0732     if(!a_func(a_out,a_level,
0733                a_srcsize,a_src,
0734                a_tgtsize,a_tgt+HDRSIZE,
0735                out_size)) {
0736       a_out << "tools::wroot::directory::zip :"
0737             << " zipper failed."
0738             << std::endl;
0739       a_irep = 0;
0740       return false;
0741     }
0742     if((HDRSIZE+out_size)>a_tgtsize) {
0743       a_out << "tools::wroot::directory::zip :"
0744             << " target buffer overflow."
0745             << std::endl;
0746       a_irep = 0;
0747       return false;
0748     }
0749 
0750     // HEADER :
0751     a_tgt[0] = 'Z'; // Signature ZLib
0752     a_tgt[1] = 'L';
0753     a_tgt[2] = 8; //DEFLATE
0754 
0755     a_tgt[3] = (char)(out_size & 0xff);
0756     a_tgt[4] = (char)((out_size >> 8) & 0xff);
0757     a_tgt[5] = (char)((out_size >> 16) & 0xff);
0758 
0759     a_tgt[6] = (char)(a_srcsize & 0xff);
0760     a_tgt[7] = (char)((a_srcsize >> 8) & 0xff);
0761     a_tgt[8] = (char)((a_srcsize >> 16) & 0xff);
0762 
0763     a_irep = HDRSIZE+out_size;
0764 
0765     return true;
0766   }
0767 
0768 #if defined(__sun) && !defined(__linux__) && (__SUNPRO_CC > 0x420)
0769   int error_number() {return ::errno;}
0770   void reset_error_number() {::errno = 0;}
0771 #else
0772   int error_number() {return errno;}
0773   void reset_error_number() {errno = 0;}
0774 #endif
0775 
0776 protected:
0777   std::ostream& m_out;
0778   std::string m_path;
0779   bool m_verbose;
0780   int m_file;
0781   //uint64 m_bytes_write; //Number of bytes write in this file
0782   std::string m_title; //must be before the below.
0783   directory m_root_directory;
0784   std::map<char,compress_func> m_zipers;
0785   std::list<free_seg*> m_free_segs; //Free segments linked list table
0786   // begin of record :
0787   // "root"
0788   uint32 m_version;       //File format version
0789   seek m_BEGIN;           //First used byte in file
0790   seek m_END;             //Last used byte in file
0791   seek m_seek_free;       //Location on disk of free segments structure
0792   uint32 m_nbytes_free;   //Number of bytes for free segments structure
0793   //int nfree
0794   uint32 m_nbytes_name;   //Number of bytes in TNamed at creation time
0795   char m_units;           //Number of bytes for file pointers
0796   uint32 m_compress;      //(=1 file is compressed, 0 otherwise)
0797   seek m_seek_info;       //Location on disk of StreamerInfo record
0798   uint32 m_nbytes_info;   //Number of bytes for StreamerInfo record
0799 };
0800 
0801 
0802 }}
0803 
0804 #endif
0805 
0806 //doc
0807 //
0808 //  A ROOT file is a suite of consecutive data records with the following
0809 //    format (see also the TKey class);
0810 // TKey ---------------------
0811 //      byte 1->4  Nbytes    = Length of compressed object (in bytes)
0812 //           5->6  Version   = TKey version identifier
0813 //           7->10 ObjLen    = Length of uncompressed object
0814 //          11->14 Datime    = Date and time when object was written to file
0815 //          15->16 KeyLen    = Length of the key structure (in bytes)
0816 //          17->18 Cycle     = Cycle of key
0817 //          19->22 SeekKey   = Pointer to record itself (consistency check)
0818 //          23->26 SeekPdir  = Pointer to directory header
0819 //          27->27 lname     = Number of bytes in the class name
0820 //          28->.. ClassName = Object Class Name
0821 //          ..->.. lname     = Number of bytes in the object name
0822 //          ..->.. Name      = lName bytes with the name of the object
0823 //          ..->.. lTitle    = Number of bytes in the object title
0824 //          ..->.. Title     = Title of the object
0825 //          -----> DATA      = Data bytes associated to the object
0826 //
0827 //  The first data record starts at byte fBEGIN (currently set to kBegin)
0828 //  Bytes 1->kBegin contain the file description:
0829 //       byte  1->4  "root"      = Root file identifier
0830 //             5->8  fVersion    = File format version
0831 //             9->12 fBEGIN      = Pointer to first data record
0832 //            13->16 fEND        = Pointer to first free word at the EOF
0833 //            17->20 fSeekFree   = Pointer to FREE data record
0834 //            21->24 fNbytesFree = Number of bytes in FREE data record
0835 //            25->28 nfree       = Number of free data records
0836 //            29->32 fNbytesName = Number of bytes in TNamed at creation time
0837 //            33->33 fUnits      = Number of bytes for file pointers
0838 //            34->37 fCompress   = Zip compression level
0839 //