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