Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/rroot/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_rroot_file
0005 #define tools_rroot_file
0006 
0007 #include "ifile"
0008 
0009 #include "directory"
0010 
0011 #include "../platform"
0012 
0013 #include "obj_list"
0014 #include "info"
0015 #include "streamer_fac"
0016 
0017 #include <string>
0018 #include <fcntl.h>
0019 #include <errno.h>
0020 
0021 #if defined(_MSC_VER) || defined(__MINGW32__)
0022 #include <io.h>
0023 #include <sys/stat.h>
0024 #else
0025 #include <unistd.h>
0026 #endif
0027 
0028 namespace tools {
0029 namespace rroot {
0030 
0031 class file : public virtual ifile {
0032   file& get_me() {return *this;} //_MSC_VER : to avoid warning about the usage of "this" in the constructor.
0033   static int not_open() {return -1;}
0034 public:
0035   static const std::string& s_class() {
0036     static const std::string s_v("tools::rroot::file");
0037     return s_v;
0038   }
0039   virtual const std::string& s_cls() const {return s_class();}
0040 public: //ifile
0041   virtual const std::string& path() const {return m_path;}
0042 
0043   virtual bool verbose() const {return m_verbose;}
0044   virtual std::ostream& out() const {return m_out;}
0045 
0046   virtual bool byte_swap() const {return is_little_endian();}
0047   virtual bool set_pos(seek a_offset = 0,from a_from = begin){
0048     int whence = 0;
0049     switch(a_from) {
0050     case begin:
0051       whence = SEEK_SET;
0052       break;
0053     case current:
0054       whence = SEEK_CUR;
0055       break;
0056     case end:
0057       whence = SEEK_END;
0058       break;
0059     }
0060 
0061 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
0062     if (::lseek64(m_file, a_offset, whence) < 0) {
0063 #elif defined(_MSC_VER) || defined(__MINGW32__)
0064     if (::_lseeki64(m_file, a_offset, whence) < 0) {
0065 #else
0066     if (::lseek(m_file, a_offset, whence) < 0) {
0067 #endif
0068       m_out << "tools::rroot::file::set_pos :"
0069             << " cannot set position " << a_offset
0070             << " in file " << sout(m_path) << "."
0071             << std::endl;
0072       return false;
0073     }
0074     return true;
0075   }
0076   virtual bool read_buffer(char* a_buffer,uint32 a_length) {
0077     // Read a buffer from the file.
0078     // This is the basic low level read operation.
0079 #ifdef _MSC_VER
0080     typedef int ssize_t;
0081 #endif
0082     ssize_t siz;
0083     while ((siz = ::read(m_file,a_buffer,a_length)) < 0 &&
0084            error_number() == EINTR) reset_error_number();
0085     if (siz < 0) {
0086       m_out << "tools::rroot::file::read_buffer :"
0087             << " error reading from file " << sout(m_path) << "."
0088             << std::endl;
0089       return false;
0090     }
0091     if (siz != ssize_t(a_length)) {
0092       m_out << "tools::rroot::file::read_buffer :"
0093             << " error reading all requested bytes from file "
0094             << sout(m_path) << ", got " << long_out(siz)
0095             << " of " << a_length
0096             << std::endl;
0097       return false;
0098     }
0099     m_bytes_read += siz;
0100     return true;
0101   }
0102   virtual bool unziper(char a_key,decompress_func& a_func) const {
0103     std::map<char,decompress_func>::const_iterator it = m_unzipers.find(a_key);
0104     if(it==m_unzipers.end()) {
0105       a_func = 0;
0106       return false;
0107     }
0108     a_func = (*it).second;
0109     return true;
0110   }
0111 
0112   virtual key& sinfos_key() {return m_streamer_infos_key;}
0113 
0114 public:
0115   file(std::ostream& a_out,const std::string& a_path,bool a_verbose = false)
0116   :m_out(a_out)
0117   ,m_path(a_path)
0118   ,m_verbose(a_verbose)
0119   ,m_file(not_open())
0120   ,m_bytes_read(0)
0121   ,m_root_directory(get_me())
0122   ,m_streamer_infos_key(a_out)
0123   ,m_streamer_fac(a_out)
0124   ,m_streamer_infos(m_streamer_fac)
0125   // begin of record :
0126   ,m_version(0)
0127   ,m_BEGIN(0)
0128   ,m_END(0)
0129   ,m_seek_free(0)
0130   ,m_seek_info(0)
0131   ,m_nbytes_free(0)
0132   ,m_nbytes_info(0)
0133   ,m_nbytes_name(0)
0134   {
0135 #ifdef TOOLS_MEM
0136     mem::increment(s_class().c_str());
0137 #endif
0138 
0139     m_file = _open(a_path.c_str(),
0140 #if defined(_MSC_VER) || defined(__MINGW32__)
0141                                O_RDONLY | O_BINARY,S_IREAD | S_IWRITE
0142 #else
0143                                O_RDONLY,0644
0144 #endif
0145     );
0146     if(m_file==not_open()) {
0147       m_out << "tools::rroot::file::file :"
0148             << " can't open " << sout(a_path) << "."
0149             << std::endl;
0150       return;
0151     }
0152     initialize();
0153   }
0154   virtual ~file() {
0155     close();
0156 #ifdef TOOLS_MEM
0157     mem::decrement(s_class().c_str());
0158 #endif
0159   }
0160 protected:
0161   file(const file& a_from)
0162   :ifile(a_from)
0163   ,m_out(a_from.m_out)
0164   ,m_root_directory(get_me())
0165   ,m_streamer_infos_key(a_from.m_out)
0166   ,m_streamer_fac(a_from.m_out)
0167   ,m_streamer_infos(m_streamer_fac)
0168   {
0169 #ifdef TOOLS_MEM
0170     mem::increment(s_class().c_str());
0171 #endif
0172   }
0173   file& operator=(const file&){return *this;}
0174 public:
0175   uint32 version() const {return m_version;}
0176 
0177   bool is_open() const {
0178     return (m_file==not_open()?false:true);
0179   }
0180 
0181   void close() {
0182     if(m_file!=not_open()) ::close(m_file);
0183     m_file = not_open();
0184     m_root_directory.clear_keys();
0185   }
0186 
0187   directory& dir() {return m_root_directory;}
0188   const directory& dir() const {return m_root_directory;}
0189 
0190   bool add_unziper(char a_key,decompress_func a_func){
0191     std::map<char,decompress_func>::const_iterator it = m_unzipers.find(a_key);
0192     if(it!=m_unzipers.end()) {
0193       //(*it).second = a_func; //override ?
0194       return false;
0195     } else {
0196       m_unzipers[a_key] = a_func;
0197       return true;
0198     }
0199   }
0200 
0201   bool dump_streamer_infos() {
0202     // read_streamer_infos_data() done here (and not in initialize) since it may need to have unziper declared.
0203     if(m_streamer_infos.empty()) {if(!read_streamer_infos_data()) return false;}
0204     tools_vforcit(iro*,m_streamer_infos,it) {
0205       streamer_info* info = safe_cast<iro,streamer_info>(*(*it));
0206       if(!info) return false;
0207       info->out(m_out);
0208     }
0209     return true;
0210   }
0211   streamer_info* find_streamer_info(const std::string& a_class) {
0212     // read_streamer_infos_data() done here (and not in initialize) since it may need to have unziper declared.
0213     if(m_streamer_infos.empty()) {if(!read_streamer_infos_data()) return 0;}
0214     tools_vforcit(iro*,m_streamer_infos,it) {
0215       streamer_info* info = safe_cast<iro,streamer_info>(*(*it));
0216       if(info) {
0217         if(info->name()==a_class) return info;
0218       }
0219     }
0220     return 0;
0221   }
0222 
0223 protected:
0224   static int _open(const char* a_name,int a_flags,uint32 a_mode) {
0225 #if defined(__linux__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2)
0226      return ::open64(a_name,a_flags,a_mode);
0227 #else
0228      return ::open(a_name,a_flags,a_mode);
0229 #endif
0230   }
0231   static std::string sout(const std::string& a_string) {return "\""+a_string+"\"";}
0232   bool initialize() {
0233     if(!read_header()) {
0234       m_out << "tools::rroot::file::initialize :"
0235             << " can't read header."
0236             << std::endl;
0237       return false;
0238     }
0239 /*
0240     fRootDirectory->setSeekDirectory(fBEGIN);
0241     // Read Free segments structure if file is writable :
0242     if (fWritable) {
0243       if (fSeekFree > fBEGIN) {
0244         if(!readFreeSegments()) {
0245           m_out << "tools::rroot::file::initialize : Cannot read free segments."
0246                << std::endl;
0247           return false;
0248         }
0249       } else {
0250         m_out << "tools::rroot::file::initialize : file \"" << fName
0251              << "\" probably not closed, cannot read free segments" << std::endl;
0252       }
0253     }
0254 */
0255     // Read Directory info :
0256     uint32 nbytes = m_nbytes_name + m_root_directory.record_size(m_version);
0257     char* header = new char[nbytes];
0258     char* buffer = header;
0259     if(!set_pos(m_BEGIN)) {
0260       m_out << "tools::rroot::file::initialize :"
0261             << " can't set position."
0262             << std::endl;
0263       delete [] header;
0264       return false;
0265     }
0266     if(!read_buffer(buffer,nbytes)) {
0267       m_out << "tools::rroot::file::initialize :"
0268             << " can't read buffer."
0269             << std::endl;
0270       delete [] header;
0271       return false;
0272     }
0273     buffer = header+m_nbytes_name;
0274     const char* eob = header+nbytes;
0275     if(!m_root_directory.from_buffer(eob,buffer)) {
0276       m_out << "tools::rroot::file::initialize :"
0277             << " can't read buffer (2)."
0278             << std::endl;
0279       delete [] header;
0280       return false;
0281     }
0282     uint32 nk =          //size of Key
0283       sizeof(int) +      //Key::fNumberOfBytes
0284       sizeof(short) +    //Key::fVersion
0285       2*sizeof(int) +    //Key::fObjectSize, Date
0286       2*sizeof(short) +  //Key::fKeyLength,fCycle
0287       2*sizeof(seek32);  //Key::fSeekKey,fSeekParentDirectory
0288                         //WARNING : the upper is seek32 since at begin of file.
0289     buffer = header+nk;
0290     std::string cname;
0291     rbuf rb(m_out,byte_swap(),eob,buffer);
0292     // Should be "TFile".
0293     if(!rb.read(cname)) {
0294       m_out << "tools::rroot::file::initialize :"
0295             << " can't read buffer (3)."
0296             << std::endl;
0297       delete [] header;
0298       return false;
0299     }
0300     if(cname!="TFile") {
0301       m_out << "tools::rroot::file::initialize : TFile expected." << std::endl;
0302       delete [] header;
0303       return false;
0304     }
0305     if(m_verbose) {
0306       m_out << "tools::rroot::file::initialize :"
0307             << " " << sout("TFile") << " found."
0308             << std::endl;
0309     }
0310     if(!rb.read(cname)) {
0311       m_out << "tools::rroot::file::initialize :"
0312             << " can't read buffer (4)."
0313             << std::endl;
0314       delete [] header;
0315       return false;
0316     }
0317     if(m_verbose) {
0318       m_out << "tools::rroot::file::initialize :"
0319             << " found file name " << sout(cname)
0320             << std::endl;
0321     }
0322     if(!rb.read(m_title)) {
0323       m_out << "tools::rroot::file::initialize :"
0324             << " can't read buffer (5)."
0325             << std::endl;
0326       delete [] header;
0327       return false;
0328     }
0329     delete [] header;
0330     if(m_verbose) {
0331       m_out << "tools::rroot::file::initialize :"
0332             << " found title " << sout(m_title)
0333             << std::endl;
0334     }
0335     uint32 dirNbytesName = m_root_directory.nbytes_name();
0336     if (dirNbytesName < 10 || dirNbytesName > 1000) {
0337       m_out << "tools::rroot::file::initialize :"
0338             << " can't read directory info."
0339             << std::endl;
0340       return false;
0341     }
0342     // Read keys of the top directory :
0343     if(m_root_directory.seek_keys() > m_BEGIN) {
0344       uint32 n;
0345       if(!m_root_directory.read_keys(n)) {
0346         m_out << "tools::rroot::file::initialize :"
0347               << " can't read keys."
0348               << std::endl;
0349         return false;
0350       }
0351     } else {
0352       m_out << "tools::rroot::file::initialize :"
0353             << " file " << sout(m_path)
0354             << " probably not closed."
0355             << std::endl;
0356       return false;
0357     }
0358 
0359     // Create StreamerInfo index
0360     if(m_seek_info > m_BEGIN) {
0361       if(!read_streamer_infos_key()) {
0362         m_out << "tools::rroot::file::initialize :"
0363               << " read_streamer_infos_key() failed."
0364               << std::endl;
0365         return false;
0366       }
0367     } else {
0368       m_out << "tools::rroot::file::initialize :"
0369             << " file " << sout(m_path)
0370             << " probably not closed."
0371             << std::endl;
0372       return false;
0373     }
0374 
0375     return true;
0376   }
0377   bool read_header() {
0378     static const uint32 kBegin = 64;
0379     char header[kBegin];
0380     if(!set_pos()) return false;
0381     if(!read_buffer(header,kBegin)) return false;
0382     // make sure this is a root file
0383     if(::strncmp(header, "root", 4)) {
0384       m_out << "tools::rroot::file::read_header :"
0385             << " " << sout(m_path) << " not a file at the CERN-ROOT format."
0386             << std::endl;
0387       return false;
0388     }
0389     if(m_verbose) {
0390       m_out << "tools::rroot::file::read_header :"
0391             << " file signature is " << sout("root")
0392             << std::endl;
0393     }
0394     char* buffer = header + 4;    // skip the "root" file identifier
0395     const char* eob = header + kBegin;
0396     rbuf rb(m_out,byte_swap(),eob,buffer);
0397    {int v;
0398     if(!rb.read(v)) return false;
0399     m_version = v;}
0400    {seek32 i;
0401     if(!rb.read(i)) return false;
0402     m_BEGIN = i;}
0403     if(m_version>1000000) {
0404       if(!rb.read(m_END)) return false;
0405       if(!rb.read(m_seek_free)) return false;
0406     } else {
0407      {seek32 i;
0408       if(!rb.read(i)) return false;
0409       m_END = i;}
0410      {seek32 i;
0411       if(!rb.read(i)) return false;
0412       m_seek_free = i;}
0413     }
0414     if(m_verbose) {
0415       m_out << "tools::rroot::file::read_header :"
0416             << " begin " << m_BEGIN
0417             << " end " << m_END
0418             << std::endl;
0419     }
0420    {int v;
0421     if(!rb.read(v)) return false;
0422     m_nbytes_free = v;}
0423     int nfree = 0;
0424     if(!rb.read(nfree)) return false;
0425    {int v;
0426     if(!rb.read(v)) return false;
0427     m_nbytes_name = v;}
0428     //m_out << "debug : 1002 " << m_nbytes_name << std::endl;
0429    {char fUnits;
0430     if(!rb.read(fUnits)) return false;}
0431    {int fCompress;
0432     if(!rb.read(fCompress)) return false;}
0433     if(m_version>1000000) {
0434       if(!rb.read(m_seek_info)) return false;
0435     } else {
0436      {seek32 i;
0437       if(!rb.read(i)) return false;
0438       m_seek_info = i;}
0439     }
0440     if(!rb.read(m_nbytes_info)) return false;
0441     //m_out << "debug : seek_info " << m_seek_info << " nbytes_info " << m_nbytes_info << std::endl;
0442     return true;
0443   }
0444 
0445   bool read_streamer_infos_key() {
0446     // Read the list of StreamerInfo from this file
0447     // The key with name holding the list of TStreamerInfo objects is read.
0448     // The corresponding TClass objects are updated.
0449     if(m_seek_info<=0) return false;
0450     if(m_seek_info>=m_END) return false;
0451     if(!set_pos(m_seek_info)) return false;
0452     char* buffer = new char[m_nbytes_info+1];
0453     if(!read_buffer(buffer,m_nbytes_info)) {delete [] buffer;return false;}
0454     char* buf = buffer;
0455     if(!m_streamer_infos_key.from_buffer(byte_swap(),buffer+m_nbytes_info,buf,m_verbose)) {
0456       delete [] buffer;
0457       return false;
0458     }
0459     delete [] buffer;
0460     return true;
0461   }
0462 
0463   bool read_streamer_infos_data() {
0464     key& k = m_streamer_infos_key;
0465     if(k.object_class()!="TList") {
0466       m_out << "tools::rroot::file::read_streamer_infos_data : key not a TList." << std::endl;
0467       return false;
0468     }
0469     unsigned int sz;
0470     char* buf = k.get_object_buffer(*this,sz); //we don't have ownership of buf.
0471     if(!buf) {
0472       m_out << "tools::rroot::file::read_streamer_infos :"
0473           << " can't get data buffer of " << k.object_name() << "."
0474           << std::endl;
0475       return false;
0476     }
0477     buffer b(m_out,byte_swap(),sz,buf,k.key_length(),false);
0478     return m_streamer_infos.stream(b);
0479   }
0480 
0481 #if defined(__sun) && !defined(__linux__) && (__SUNPRO_CC > 0x420)
0482   int error_number() {return ::errno;}
0483   void reset_error_number() {::errno = 0;}
0484 #else
0485   int error_number() {return errno;}
0486   void reset_error_number() {errno = 0;}
0487 #endif
0488 
0489 protected:
0490   std::ostream& m_out;
0491   std::string m_path;
0492   bool m_verbose;
0493   int m_file;
0494   uint64 m_bytes_read; //Number of bytes read from this file
0495   directory m_root_directory;
0496   key m_streamer_infos_key;
0497   streamer_fac m_streamer_fac;
0498   obj_list m_streamer_infos;
0499   std::map<char,decompress_func> m_unzipers;
0500   std::string m_title;
0501   // begin of record :
0502   uint32 m_version;       //File format version
0503   seek m_BEGIN;           //First used byte in file
0504   seek m_END;             //Last used byte in file
0505   seek m_seek_free;       //Location on disk of free segments structure
0506   seek m_seek_info;       //Location on disk of StreamerInfo record
0507   uint32 m_nbytes_free;   //Number of bytes for free segments structure
0508   uint32 m_nbytes_info;   //Number of bytes for StreamerInfo record
0509   //int nfree
0510   uint32 m_nbytes_name;   //Number of bytes in TNamed at creation time
0511 };
0512 
0513 
0514 }}
0515 
0516 #endif
0517 
0518 //doc
0519 //
0520 //  A ROOT file is a suite of consecutive data records with the following
0521 //    format (see also the TKey class);
0522 // TKey ---------------------
0523 //      byte 1->4  Nbytes    = Length of compressed object (in bytes)
0524 //           5->6  Version   = TKey version identifier
0525 //           7->10 ObjLen    = Length of uncompressed object
0526 //          11->14 Datime    = Date and time when object was written to file
0527 //          15->16 KeyLen    = Length of the key structure (in bytes)
0528 //          17->18 Cycle     = Cycle of key
0529 //          19->22 SeekKey   = Pointer to record itself (consistency check)
0530 //          23->26 SeekPdir  = Pointer to directory header
0531 //          27->27 lname     = Number of bytes in the class name
0532 //          28->.. ClassName = Object Class Name
0533 //          ..->.. lname     = Number of bytes in the object name
0534 //          ..->.. Name      = lName bytes with the name of the object
0535 //          ..->.. lTitle    = Number of bytes in the object title
0536 //          ..->.. Title     = Title of the object
0537 //          -----> DATA      = Data bytes associated to the object
0538 //
0539 //  The first data record starts at byte fBEGIN (currently set to kBegin)
0540 //  Bytes 1->kBegin contain the file description:
0541 //       byte  1->4  "root"      = Root file identifier
0542 //             5->8  fVersion    = File format version
0543 //             9->12 fBEGIN      = Pointer to first data record
0544 //            13->16 fEND        = Pointer to first free word at the EOF
0545 //            17->20 fSeekFree   = Pointer to FREE data record
0546 //            21->24 fNbytesFree = Number of bytes in FREE data record
0547 //            25->28 nfree       = Number of free data records
0548 //            29->32 fNbytesName = Number of bytes in TNamed at creation time
0549 //            33->33 fUnits      = Number of bytes for file pointers
0550 //            34->37 fCompress   = Zip compression level
0551 //