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