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 //////////////////////////////////////////////////////////////////////////