Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/rroot/key 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_key
0005 #define tools_rroot_key
0006 
0007 #include "rbuf"
0008 #include "seek"
0009 #include "date"
0010 #include "ifile"
0011 #include "../sout"
0012 
0013 #include <map>
0014 #include <ostream>
0015 #include <cstring> //memcpy
0016 
0017 namespace tools {
0018 namespace rroot {
0019 //doc :
0020 //////////////////////////////////////////////////////////////////////////
0021 //                                                                      //
0022 //  The Key class includes functions to book space on a file,           //
0023 //   to create I/O buffers, to fill these buffers                       //
0024 //   to compress/uncompress data buffers.                               //
0025 //                                                                      //
0026 //  Before saving (making persistent) an object on a file, a key must   //
0027 //  be created. The key structure contains all the information to       //
0028 //  uniquely identify a persistent object on a file.                    //
0029 //     fNbytes    = number of bytes for the compressed object+key       //
0030 //     version of the Key class                                         //
0031 //     fObjlen    = Length of uncompressed object                       //
0032 //     fDatime    = Date/Time when the object was written               //
0033 //     fKeylen    = number of bytes for the key structure               //
0034 //     fCycle     = cycle number of the object                          //
0035 //     fSeekKey   = Address of the object on file (points to fNbytes)   //
0036 //                  This is a redundant information used to cross-check //
0037 //                  the data base integrity.                            //
0038 //     fSeekPdir  = Pointer to the directory supporting this object     //
0039 //     fClassName = Object class name                                   //
0040 //     fName      = name of the object                                  //
0041 //     fTitle     = title of the object                                 //
0042 //                                                                      //
0043 //  The Key class is used by ROOT to:                                   //
0044 //    - to write an object in the Current Directory                     //
0045 //    - to write a new ntuple buffer                                    //
0046 //                                                                      //
0047 //////////////////////////////////////////////////////////////////////////
0048 
0049 class key {
0050   static uint32 class_version() {return 2;}
0051 public:
0052   static uint32 std_string_record_size(const std::string& x) {
0053     // Returns size string will occupy on I/O buffer.
0054     if (x.size() > 254)
0055       return uint32(x.size()+sizeof(unsigned char)+sizeof(int));
0056     else
0057       return uint32(x.size()+sizeof(unsigned char));
0058   }
0059 
0060 public:
0061   key(std::ostream& a_out)
0062   :m_out(a_out)
0063   ,m_buf_size(0)
0064   ,m_buffer(0)
0065   // Record :
0066   ,m_nbytes(0)
0067   ,m_version(class_version())
0068   ,m_object_size(0)
0069   ,m_date(0)
0070   ,m_key_length(0)
0071   ,m_cycle(0)
0072   ,m_seek_key(0)
0073   ,m_seek_parent_dir(0)
0074   {
0075     m_key_length = record_size(m_version);
0076   }
0077 
0078   key(std::ostream& a_out,seek a_pos,uint32 a_nbytes)
0079   :m_out(a_out)
0080   ,m_buf_size(0)
0081   ,m_buffer(0)
0082   // Record :
0083   ,m_nbytes(a_nbytes) //key len + compressed object size
0084   ,m_version(class_version())
0085   ,m_object_size(0)
0086   ,m_date(0)
0087   ,m_key_length(0)
0088   ,m_cycle(0)
0089   ,m_seek_key(a_pos)
0090   ,m_seek_parent_dir(0)
0091   {
0092     if(a_pos>START_BIG_FILE) m_version += big_file_version_tag();
0093     m_buffer = new char[a_nbytes];
0094     if(!m_buffer) {
0095       m_out << "tools::rroot::key::key(cpcstor) :"
0096                    << " can't alloc " << a_nbytes << "."
0097                    << std::endl;
0098     } else {
0099       m_buf_size = a_nbytes;
0100     }
0101   }
0102   virtual ~key(){
0103     delete [] m_buffer;
0104   }
0105 protected:
0106   key(const key& a_from)
0107   :m_out(a_from.m_out)
0108   ,m_buf_size(0)
0109   ,m_buffer(0)
0110   ,m_nbytes(a_from.m_nbytes)
0111   ,m_version(a_from.m_version)
0112   ,m_object_size(a_from.m_object_size)
0113   ,m_date(a_from.m_date)
0114   ,m_key_length(a_from.m_key_length)
0115   ,m_cycle(a_from.m_cycle)
0116   ,m_seek_key(a_from.m_seek_key)
0117   ,m_seek_parent_dir(a_from.m_seek_parent_dir)
0118   ,m_object_class(a_from.m_object_class)
0119   ,m_object_name(a_from.m_object_name)
0120   ,m_object_title(a_from.m_object_title)
0121   {
0122     if(a_from.m_buf_size && a_from.m_buffer) {
0123       m_buffer = new char[a_from.m_buf_size];
0124       if(!m_buffer) {
0125         m_out << "tools::rroot::key::key(cpcstor) :"
0126                      << " can't alloc " << a_from.m_buf_size << "."
0127                      << std::endl;
0128       } else {
0129         m_buf_size = a_from.m_buf_size;
0130         ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
0131       }
0132     }
0133   }
0134 public:
0135   key& operator=(const key& a_from){
0136     if(&a_from==this) return *this;
0137     m_nbytes = a_from.m_nbytes;
0138     m_version = a_from.m_version;
0139     m_object_size = a_from.m_object_size;
0140     m_date = a_from.m_date;
0141     m_key_length = a_from.m_key_length;
0142     m_cycle = a_from.m_cycle;
0143     m_seek_key = a_from.m_seek_key;
0144     m_seek_parent_dir = a_from.m_seek_parent_dir;
0145     m_object_class = a_from.m_object_class;
0146     m_object_name = a_from.m_object_name;
0147     m_object_title = a_from.m_object_title;
0148 
0149     delete [] m_buffer;
0150     m_buffer = 0;
0151     m_buf_size = 0;
0152 
0153     if(a_from.m_buf_size && a_from.m_buffer) {
0154       m_buffer = new char[a_from.m_buf_size];
0155       if(!m_buffer) {
0156         m_out << "tools::rroot::key::operator=() :"
0157                      << " can't alloc " << a_from.m_buf_size << "."
0158                      << std::endl;
0159       } else {
0160         m_buf_size = a_from.m_buf_size;
0161         ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
0162       }
0163     }
0164 
0165     return *this;
0166   }
0167 
0168 public:
0169   std::ostream& out() const {return m_out;}
0170 
0171   uint32 nbytes() const {return m_nbytes;}
0172   seek seek_key() const {return m_seek_key;}
0173   uint32 object_size() const {return m_object_size;}
0174 
0175   const std::string& object_name() const {return m_object_name;}
0176   const std::string& object_title() const {return m_object_title;}
0177   const std::string& object_class() const {return m_object_class;}
0178 
0179   bool read_file(ifile& a_file){
0180     // Read the key structure from the file.
0181     if(!a_file.set_pos(m_seek_key)) return false;
0182     if(!a_file.read_buffer(m_buffer,m_nbytes)) return false;
0183     if(a_file.verbose()) {
0184       m_out << "tools::rroot::key::read_file :"
0185                    << " reading " << m_nbytes << " bytes"
0186                    << " at position " << m_seek_key
0187                    << "."
0188                    << std::endl;
0189     }
0190     return true;
0191   }
0192 
0193   char* buf() const {return m_buffer;}
0194   char* data_buffer() const {return m_buffer + m_key_length;}
0195   const char* eob() const {return m_buffer + m_buf_size;}
0196   uint32 buf_size() const {return m_buf_size;}
0197   uint32 key_length() const {return m_key_length;}
0198 
0199   bool from_buffer(bool a_byte_swap,const char* aEOB,char*& a_pos,bool a_verbose) {
0200     rbuf rb(m_out,a_byte_swap,aEOB,a_pos);
0201     int _nbytes;
0202     if(!rb.read(_nbytes)) return false;
0203 
0204     m_nbytes = _nbytes;
0205     short version;
0206     if(!rb.read(version)) return false;
0207     m_version = version;
0208    {int v;
0209     if(!rb.read(v)) return false;
0210     m_object_size = v;}
0211     unsigned int _date;
0212     if(!rb.read(_date)) return false;
0213    {short v;
0214     if(!rb.read(v)) return false;
0215     m_key_length = v;}
0216    {short v;
0217     if(!rb.read(v)) return false;
0218     m_cycle = v;}
0219     if(version>(short)big_file_version_tag()) {
0220       if(!rb.read(m_seek_key)) return false;
0221       if(!rb.read(m_seek_parent_dir)) return false;
0222     } else {
0223      {seek32 i;
0224       if(!rb.read(i)) return false;
0225       m_seek_key = i;}
0226      {seek32 i;
0227       if(!rb.read(i)) return false;
0228       m_seek_parent_dir = i;}
0229     }
0230     if(!rb.read(m_object_class)) return false;
0231     if(!rb.read(m_object_name)) return false;
0232     if(!rb.read(m_object_title)) return false;
0233     if(a_verbose) {
0234       m_out << "tools::rroot::key::from_buffer :"
0235                    << " nbytes : " << m_nbytes
0236                    << ", object class : " << sout(m_object_class)
0237                    << ", object name : " << sout(m_object_name)
0238                    << ", object title : " << sout(m_object_title)
0239                    << ", object size : " << m_object_size
0240                    << "."
0241                    << std::endl;
0242     }
0243     return true;
0244   }
0245 
0246   char* get_object_buffer(ifile& a_file,uint32& a_size) {
0247     if(!m_key_length) {
0248       m_out << "tools::rroot::key::get_object_buffer :"
0249                    << " WARNING : m_key_length is zero."
0250                    << std::endl;
0251     }
0252     if(!m_nbytes) {
0253       m_out << "tools::rroot::key::get_object_buffer :"
0254                    << " m_nbytes is zero."
0255                    << std::endl;
0256       delete [] m_buffer;
0257       m_buffer = 0;
0258       m_buf_size = 0;
0259       a_size = 0;
0260       return 0;
0261     }
0262     if(!m_object_size) {
0263       m_out << "tools::rroot::key::get_object_buffer :"
0264                    << " WARNING : m_object_size is zero."
0265                    << std::endl;
0266     }
0267 
0268     if(a_file.verbose()) {
0269       m_out << "tools::rroot::key::get_object_buffer :"
0270                    << " m_nbytes : " << m_nbytes
0271                    << " m_key_length : " << m_key_length
0272                    << " m_object_size : " << m_object_size << "."
0273                    << " m_seek_key : " << m_seek_key << "."
0274                    << std::endl;
0275     }
0276 
0277     if(m_object_size <= (m_nbytes-m_key_length)) {
0278       delete [] m_buffer;
0279       m_buf_size = m_key_length+m_object_size;
0280       if(m_buf_size<m_nbytes) {
0281         m_out << "tools::rroot::key::get_object_buffer :"
0282                      << " WARNING : m_buf_size<m_nbytes."
0283                      << " m_buf_size " << m_buf_size
0284                      << " m_nbytes " << m_nbytes
0285                      << ". Raise m_buf_size to " << m_nbytes << "."
0286                      << std::endl;
0287         m_buf_size = m_nbytes; //for read_file()
0288       }
0289       m_buffer = new char[m_buf_size];
0290       if(!m_buffer) {
0291         m_out << "tools::rroot::key::get_object_buffer :"
0292                      << " can't alloc " << m_buf_size
0293                      << std::endl;
0294         m_buffer = 0;
0295         m_buf_size = 0;
0296         a_size = 0;
0297         return 0;
0298       }
0299 
0300       if(!read_file(a_file)) {
0301         delete [] m_buffer;
0302         m_buffer = 0;
0303         m_buf_size = 0;
0304         a_size = 0;
0305         return 0;
0306       }
0307 
0308     } else {
0309       // have to decompress. Need a second buffer.
0310 
0311       uint32 decsiz = m_key_length+m_object_size;
0312       char* decbuf = new char[decsiz];
0313       if(!decbuf) {
0314         m_out << "tools::rroot::key::get_object_buffer :"
0315                      << " can't alloc " << decsiz
0316                      << std::endl;
0317         a_size = 0;
0318         return 0;
0319       }
0320 
0321       delete [] m_buffer;
0322       m_buffer = new char[m_nbytes];
0323       m_buf_size = m_nbytes;
0324       if(!read_file(a_file)) {
0325         delete [] decbuf;
0326         decbuf = 0;
0327         delete [] m_buffer;
0328         m_buffer = 0;
0329         m_buf_size = 0;
0330         a_size = 0;
0331         return 0;
0332       }
0333 
0334       ::memcpy(decbuf,m_buffer,m_key_length);
0335 
0336       // decompress :
0337       unsigned char* objbuf = (unsigned char*)(decbuf+m_key_length);
0338       unsigned char* bufcur = (unsigned char*)(m_buffer+m_key_length);
0339       int nout = 0;
0340       uint32 noutot = 0;
0341       while(true) {
0342         int nin = 9 + ((int)bufcur[3] | ((int)bufcur[4] << 8) | ((int)bufcur[5] << 16));
0343         int nbuf = (int)bufcur[6] | ((int)bufcur[7] << 8) | ((int)bufcur[8] << 16);
0344         if(!unzip(m_out,a_file,nin,bufcur,nbuf,objbuf,nout)) break;
0345         if(!nout) break;
0346         noutot += nout;
0347         if(noutot >= m_object_size) break;
0348         bufcur += nin;
0349         objbuf += nout;
0350       }
0351 
0352       delete [] m_buffer;
0353       m_buffer = 0;
0354       m_buf_size = 0;
0355 
0356       if(!noutot) {
0357         m_out << "tools::rroot::key::get_object_buffer :"
0358                      << " nothing from decompression."
0359                      << std::endl;
0360         delete [] decbuf;
0361         decbuf = 0;
0362         a_size = 0;
0363         return 0;
0364       }
0365       if(noutot!=m_object_size) {
0366         m_out << "tools::rroot::key::get_object_buffer :"
0367                      << " decompression mismatch."
0368                      << " noutot " << noutot
0369                      << " m_object_size " << m_object_size
0370                      << std::endl;
0371         delete [] decbuf;
0372         decbuf = 0;
0373         a_size = 0;
0374         return 0;
0375       }
0376 
0377       m_buffer = decbuf;
0378       m_buf_size = decsiz;
0379 
0380     }
0381     a_size = m_object_size;
0382     return m_buffer+m_key_length;
0383   }
0384   //NOTE : print is a Python keyword.
0385   void dump(std::ostream& a_out) const {
0386     a_out << "class : " << sout(m_object_class)
0387           << ", name : " << sout(m_object_name)
0388           << ", title : " << sout(m_object_title)
0389           << ", size : " << m_object_size
0390           << "."
0391           << std::endl;
0392   }
0393 
0394 protected:
0395   static const uint32 START_BIG_FILE = 2000000000;
0396 protected:
0397   uint32 record_size(uint32 a_version) const {
0398     // Return the size in bytes of the key header structure.
0399     uint32 _nbytes = sizeof(m_nbytes);
0400     _nbytes += sizeof(short);         //2
0401     _nbytes += sizeof(m_object_size);
0402     _nbytes += sizeof(date);
0403     _nbytes += sizeof(m_key_length);
0404     _nbytes += sizeof(m_cycle);       //2+4*4=18
0405     if(a_version>big_file_version_tag()) {
0406       _nbytes += sizeof(seek);
0407       _nbytes += sizeof(seek);        //18+2*8=34
0408     } else {
0409       _nbytes += sizeof(seek32);
0410       _nbytes += sizeof(seek32);      //18+2*4=26
0411     }
0412     _nbytes += std_string_record_size(m_object_class);
0413     _nbytes += std_string_record_size(m_object_name);
0414     _nbytes += std_string_record_size(m_object_title);
0415     //::printf("debug : record_size %d\n",_nbytes);
0416     return _nbytes;
0417   }
0418 
0419   bool unzip(std::ostream& a_out,ifile& a_file,
0420              int a_srcsize,unsigned char* a_src,int a_tgtsize,unsigned char* a_tgt,int& a_irep) {
0421 
0422     // Author: E.Chernyaev (IHEP/Protvino)
0423     // Input: scrsize - size of input buffer
0424     //       src     - input buffer
0425     //       tgtsize - size of target buffer
0426     //
0427     // Output: tgt - target buffer (decompressed)
0428     //        irep - size of decompressed data
0429     //        0 - if error
0430 
0431     a_irep = 0;
0432 
0433     // C H E C K   H E A D E R
0434     const int HDRSIZE = 9;
0435 
0436     if (a_srcsize < HDRSIZE) {
0437       a_out << "tools::rroot::key::unzip : too small source" << std::endl;
0438       return false;
0439     }
0440 
0441     unsigned char DEFLATE = 8;
0442 
0443     if ((a_src[0] != 'C' && a_src[0] != 'Z') ||
0444         (a_src[1] != 'S' && a_src[1] != 'L') ||
0445         a_src[2] != DEFLATE) {
0446       a_out << "tools::rroot::key::unzip : error in header" << std::endl;
0447       return false;
0448     }
0449 
0450     long _ibufcnt = (long)a_src[3] | ((long)a_src[4] << 8) | ((long)a_src[5] << 16);
0451     long isize = (long)a_src[6] | ((long)a_src[7] << 8) | ((long)a_src[8] << 16);
0452 
0453     if(a_tgtsize<isize) {
0454       a_out << "tools::rroot::key::unzip : too small target." << std::endl;
0455       return false;
0456     }
0457 
0458     if(_ibufcnt + HDRSIZE != a_srcsize) {
0459       a_out << "tools::rroot::key::unzip :"
0460             << " discrepancy in source length." << std::endl;
0461       return false;
0462     }
0463 
0464     // D E C O M P R E S S   D A T A
0465 
0466     if (a_src[0] == 'Z' && a_src[1] == 'L') { //compressed with zlib.
0467       decompress_func func;
0468       if(!a_file.unziper('Z',func)) {
0469         a_out << "tools::rroot::key::unzip : "
0470               << " zlib unziper not found." << std::endl;
0471         return false;
0472       }
0473 
0474       unsigned int irep;
0475       char* src = (char*)(a_src + HDRSIZE);
0476       if(!func(a_out,
0477                (unsigned int)a_srcsize,src,
0478                (unsigned int)a_tgtsize,(char*)a_tgt,irep)) {
0479         a_out << "tools::rroot::key::unzip : "
0480               << " unzip function failed." << std::endl;
0481         a_irep = 0;
0482         return false;
0483       }
0484       a_irep = irep;
0485     } else {
0486       a_out << "tools::rroot::key::_unzip : unknown a_src[0,1]."
0487             << " [0] = " << a_src[0] << ", [1] = " << a_src[1]
0488             << std::endl;
0489       a_irep = 0;
0490       return false;
0491     }
0492     return true;
0493   }
0494 
0495   static const std::string& s_class() {
0496     static const std::string s_v("tools::rroot::key");
0497     return s_v;
0498   }
0499 protected:
0500   std::ostream& m_out;
0501   uint32 m_buf_size;
0502   char* m_buffer;
0503   // Record (stored in file) :
0504   uint32 m_nbytes;               //Number of bytes for the object on file
0505   uint32 m_version;              //Key version identifier
0506   uint32 m_object_size;          //Length of uncompressed object in bytes
0507   date m_date;                //Date/Time of insertion in file
0508   uint16 m_key_length;         //Number of bytes for the key itself
0509   uint16 m_cycle;              //Cycle number
0510   seek m_seek_key;            //Location of object on file
0511   seek m_seek_parent_dir;     //Location of parent directory on file
0512   std::string m_object_class; //Object Class name.
0513   std::string m_object_name;  //name of the object.
0514   std::string m_object_title; //title of the object.
0515 };
0516 
0517 }}
0518 
0519 #endif
0520