Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef tools_rroot_key 5 #define tools_rroot_key 6 7 #include "rbuf" 8 #include "seek" 9 #include "date" 10 #include "ifile" 11 #include "../sout" 12 13 #ifdef TOOLS_MEM 14 #include "../mem" 15 #endif 16 17 #include <map> 18 #include <ostream> 19 #include <cstring> //memcpy 20 21 //#include <zlib.h> 22 23 #ifdef TOOLS_USE_CSZ 24 // CSZ code where used as default compressor i 25 // to read old file (as the pawdemo.root one). 26 //FIXME : arrange to have csz coming from the 27 extern "C" { 28 void csz__Init_Inflate(long,unsigned char*,l 29 int csz__Inflate(); 30 unsigned char* csz__obufptr(); 31 } 32 #endif 33 34 namespace tools { 35 namespace rroot { 36 37 class key { 38 static uint32 class_version() {return 2;} 39 public: 40 static uint32 std_string_record_size(const s 41 // Returns size string will occupy on I/O 42 if (x.size() > 254) 43 return uint32(x.size()+sizeof(unsigned c 44 else 45 return uint32(x.size()+sizeof(unsigned c 46 } 47 48 public: 49 key(std::ostream& a_out) 50 :m_out(a_out) 51 ,m_buf_size(0) 52 ,m_buffer(0) 53 // Record : 54 ,m_nbytes(0) 55 ,m_version(class_version()) 56 ,m_object_size(0) 57 ,m_date(0) 58 ,m_key_length(0) 59 ,m_cycle(0) 60 ,m_seek_key(0) 61 ,m_seek_parent_dir(0) 62 //,m_object_class 63 //,m_object_name 64 //,m_object_title 65 { 66 #ifdef TOOLS_MEM 67 mem::increment(s_class().c_str()); 68 #endif 69 m_key_length = record_size(m_version); 70 //fDate.setDate(0); 71 } 72 73 key(std::ostream& a_out,seek a_pos,uint32 a_ 74 :m_out(a_out) 75 ,m_buf_size(0) 76 ,m_buffer(0) 77 // Record : 78 ,m_nbytes(a_nbytes) //key len + compressed o 79 ,m_version(class_version()) 80 ,m_object_size(0) 81 ,m_date(0) 82 ,m_key_length(0) 83 ,m_cycle(0) 84 ,m_seek_key(a_pos) 85 ,m_seek_parent_dir(0) 86 //,m_object_class 87 //,m_object_name 88 //,m_object_title 89 { 90 #ifdef TOOLS_MEM 91 mem::increment(s_class().c_str()); 92 #endif 93 if(a_pos>START_BIG_FILE) m_version += big_ 94 m_buffer = new char[a_nbytes]; 95 if(!m_buffer) { 96 m_out << "tools::rroot::key::key(cpcstor 97 << " can't alloc " << a_nby 98 << std::endl; 99 } else { 100 m_buf_size = a_nbytes; 101 } 102 } 103 virtual ~key(){ 104 delete [] m_buffer; 105 #ifdef TOOLS_MEM 106 mem::decrement(s_class().c_str()); 107 #endif 108 } 109 protected: 110 key(const key& a_from) 111 :m_out(a_from.m_out) 112 ,m_buf_size(0) 113 ,m_buffer(0) 114 ,m_nbytes(a_from.m_nbytes) 115 ,m_version(a_from.m_version) 116 ,m_object_size(a_from.m_object_size) 117 ,m_date(a_from.m_date) 118 ,m_key_length(a_from.m_key_length) 119 ,m_cycle(a_from.m_cycle) 120 ,m_seek_key(a_from.m_seek_key) 121 ,m_seek_parent_dir(a_from.m_seek_parent_dir) 122 ,m_object_class(a_from.m_object_class) 123 ,m_object_name(a_from.m_object_name) 124 ,m_object_title(a_from.m_object_title) 125 { 126 #ifdef TOOLS_MEM 127 mem::increment(s_class().c_str()); 128 #endif 129 if(a_from.m_buf_size && a_from.m_buffer) { 130 m_buffer = new char[a_from.m_buf_size]; 131 if(!m_buffer) { 132 m_out << "tools::rroot::key::key(cpcst 133 << " can't alloc " << a_f 134 << std::endl; 135 } else { 136 m_buf_size = a_from.m_buf_size; 137 ::memcpy(m_buffer,a_from.m_buffer,a_fr 138 } 139 } 140 } 141 public: 142 key& operator=(const key& a_from){ 143 if(&a_from==this) return *this; 144 m_nbytes = a_from.m_nbytes; 145 m_version = a_from.m_version; 146 m_object_size = a_from.m_object_size; 147 m_date = a_from.m_date; 148 m_key_length = a_from.m_key_length; 149 m_cycle = a_from.m_cycle; 150 m_seek_key = a_from.m_seek_key; 151 m_seek_parent_dir = a_from.m_seek_parent_d 152 m_object_class = a_from.m_object_class; 153 m_object_name = a_from.m_object_name; 154 m_object_title = a_from.m_object_title; 155 156 delete [] m_buffer; 157 m_buffer = 0; 158 m_buf_size = 0; 159 160 if(a_from.m_buf_size && a_from.m_buffer) { 161 m_buffer = new char[a_from.m_buf_size]; 162 if(!m_buffer) { 163 m_out << "tools::rroot::key::operator= 164 << " can't alloc " << a_f 165 << std::endl; 166 } else { 167 m_buf_size = a_from.m_buf_size; 168 ::memcpy(m_buffer,a_from.m_buffer,a_fr 169 } 170 } 171 172 return *this; 173 } 174 175 public: 176 std::ostream& out() const {return m_out;} 177 178 uint32 nbytes() const {return m_nbytes;} 179 seek seek_key() const {return m_seek_key;} 180 uint32 object_size() const {return m_object_ 181 182 const std::string& object_name() const {retu 183 const std::string& object_title() const {ret 184 const std::string& object_class() const {ret 185 186 bool read_file(ifile& a_file){ 187 // Read the key structure from the file. 188 if(!a_file.set_pos(m_seek_key)) return fal 189 if(!a_file.read_buffer(m_buffer,m_nbytes)) 190 if(a_file.verbose()) { 191 m_out << "tools::rroot::key::read_file : 192 << " reading " << m_nbytes 193 << " at position " << m_see 194 << "." 195 << std::endl; 196 } 197 return true; 198 } 199 200 char* buf() const {return m_buffer;} 201 char* data_buffer() const {return m_buffer + 202 const char* eob() const {return m_buffer + m 203 uint32 buf_size() const {return m_buf_size;} 204 uint32 key_length() const {return m_key_leng 205 206 bool from_buffer(bool a_byte_swap,const char 207 rbuf rb(m_out,a_byte_swap,aEOB,a_pos); 208 int _nbytes; 209 if(!rb.read(_nbytes)) return false; 210 /* 211 if(m_nbytes) { 212 if(_nbytes!=int(m_nbytes)) { 213 out << "tools::rroot::key::from_buffer 214 << " nbytes not consistent." 215 << " read " << _nbytes 216 << ", expected " << m_nbytes 217 << ". Continue with " << _nbytes 218 << std::endl; 219 m_nbytes = _nbytes; 220 } 221 } else { 222 */ 223 m_nbytes = _nbytes; 224 //} 225 short version; 226 if(!rb.read(version)) return false; 227 m_version = version; 228 {int v; 229 if(!rb.read(v)) return false; 230 m_object_size = v;} 231 unsigned int _date; 232 if(!rb.read(_date)) return false; 233 //fDate.setDate(_date); 234 {short v; 235 if(!rb.read(v)) return false; 236 m_key_length = v;} 237 {short v; 238 if(!rb.read(v)) return false; 239 m_cycle = v;} 240 if(version>(short)big_file_version_tag()) 241 if(!rb.read(m_seek_key)) return false; 242 if(!rb.read(m_seek_parent_dir)) return f 243 } else { 244 {seek32 i; 245 if(!rb.read(i)) return false; 246 m_seek_key = i;} 247 {seek32 i; 248 if(!rb.read(i)) return false; 249 m_seek_parent_dir = i;} 250 } 251 if(!rb.read(m_object_class)) return false; 252 if(!rb.read(m_object_name)) return false; 253 if(!rb.read(m_object_title)) return false; 254 if(a_verbose) { 255 m_out << "tools::rroot::key::from_buffer 256 << " nbytes : " << m_nbytes 257 << ", object class : " << s 258 << ", object name : " << so 259 << ", object title : " << s 260 << ", object size : " << m_ 261 << "." 262 << std::endl; 263 } 264 return true; 265 } 266 267 char* get_object_buffer(ifile& a_file,uint32 268 if(!m_key_length) { 269 m_out << "tools::rroot::key::get_object_ 270 << " WARNING : m_key_length 271 << std::endl; 272 //delete [] m_buffer; 273 //m_buffer = 0; 274 //m_buf_size = 0; 275 //a_size = 0; 276 //return 0; 277 } 278 if(!m_nbytes) { 279 m_out << "tools::rroot::key::get_object_ 280 << " m_nbytes is zero." 281 << std::endl; 282 delete [] m_buffer; 283 m_buffer = 0; 284 m_buf_size = 0; 285 a_size = 0; 286 return 0; 287 } 288 if(!m_object_size) { 289 m_out << "tools::rroot::key::get_object_ 290 << " WARNING : m_object_siz 291 << std::endl; 292 } 293 294 if(a_file.verbose()) { 295 m_out << "tools::rroot::key::get_object_ 296 << " m_nbytes : " << m_nbyt 297 << " m_key_length : " << m_ 298 << " m_object_size : " << m 299 << " m_seek_key : " << m_se 300 << std::endl; 301 } 302 303 if(m_object_size <= (m_nbytes-m_key_length 304 delete [] m_buffer; 305 m_buf_size = m_key_length+m_object_size; 306 if(m_buf_size<m_nbytes) { 307 m_out << "tools::rroot::key::get_objec 308 << " WARNING : m_buf_size 309 << " m_buf_size " << m_bu 310 << " m_nbytes " << m_nbyt 311 << ". Raise m_buf_size to 312 << std::endl; 313 m_buf_size = m_nbytes; //for read_file 314 } 315 m_buffer = new char[m_buf_size]; 316 if(!m_buffer) { 317 m_out << "tools::rroot::key::get_objec 318 << " can't alloc " << m_b 319 << std::endl; 320 m_buffer = 0; 321 m_buf_size = 0; 322 a_size = 0; 323 return 0; 324 } 325 326 if(!read_file(a_file)) { 327 delete [] m_buffer; 328 m_buffer = 0; 329 m_buf_size = 0; 330 a_size = 0; 331 return 0; 332 } 333 334 } else { 335 // have to decompress. Need a second buf 336 337 uint32 decsiz = m_key_length+m_object_si 338 char* decbuf = new char[decsiz]; 339 if(!decbuf) { 340 m_out << "tools::rroot::key::get_objec 341 << " can't alloc " << dec 342 << std::endl; 343 a_size = 0; 344 return 0; 345 } 346 347 delete [] m_buffer; 348 m_buffer = new char[m_nbytes]; 349 m_buf_size = m_nbytes; 350 if(!read_file(a_file)) { 351 delete [] decbuf; 352 decbuf = 0; 353 delete [] m_buffer; 354 m_buffer = 0; 355 m_buf_size = 0; 356 a_size = 0; 357 return 0; 358 } 359 360 ::memcpy(decbuf,m_buffer,m_key_length); 361 362 // decompress : 363 unsigned char* objbuf = (unsigned char*) 364 unsigned char* bufcur = (unsigned char*) 365 int nout = 0; 366 uint32 noutot = 0; 367 while(true) { 368 int nin = 9 + ((int)bufcur[3] | ((int) 369 int nbuf = (int)bufcur[6] | ((int)bufc 370 if(!unzip(m_out,a_file,nin,bufcur,nbuf 371 if(!nout) break; 372 noutot += nout; 373 if(noutot >= m_object_size) break; 374 bufcur += nin; 375 objbuf += nout; 376 } 377 378 delete [] m_buffer; 379 m_buffer = 0; 380 m_buf_size = 0; 381 382 if(!noutot) { 383 m_out << "tools::rroot::key::get_objec 384 << " nothing from decompr 385 << std::endl; 386 delete [] decbuf; 387 decbuf = 0; 388 a_size = 0; 389 return 0; 390 } 391 if(noutot!=m_object_size) { 392 m_out << "tools::rroot::key::get_objec 393 << " decompression mismat 394 << " noutot " << noutot 395 << " m_object_size " << m 396 << std::endl; 397 delete [] decbuf; 398 decbuf = 0; 399 a_size = 0; 400 return 0; 401 } 402 403 m_buffer = decbuf; 404 m_buf_size = decsiz; 405 406 } 407 a_size = m_object_size; 408 return m_buffer+m_key_length; 409 } 410 //NOTE : print is a Python keyword. 411 void dump(std::ostream& a_out) const { 412 a_out << "class : " << sout(m_object_class 413 << ", name : " << sout(m_object_name 414 << ", title : " << sout(m_object_tit 415 << ", size : " << m_object_size 416 << "." 417 << std::endl; 418 } 419 420 protected: 421 static const uint32 START_BIG_FILE = 2000000 422 protected: 423 uint32 record_size(uint32 a_version) const { 424 // Return the size in bytes of the key hea 425 uint32 _nbytes = sizeof(m_nbytes); 426 _nbytes += sizeof(short); //2 427 _nbytes += sizeof(m_object_size); 428 _nbytes += sizeof(date); 429 _nbytes += sizeof(m_key_length); 430 _nbytes += sizeof(m_cycle); //2+4*4= 431 if(a_version>big_file_version_tag()) { 432 _nbytes += sizeof(seek); 433 _nbytes += sizeof(seek); //18+2*8 434 } else { 435 _nbytes += sizeof(seek32); 436 _nbytes += sizeof(seek32); //18+2*4 437 } 438 _nbytes += std_string_record_size(m_object 439 _nbytes += std_string_record_size(m_object 440 _nbytes += std_string_record_size(m_object 441 //::printf("debug : record_size %d\n",_nby 442 return _nbytes; 443 } 444 445 bool unzip(std::ostream& a_out,ifile& a_file 446 int a_srcsize,unsigned char* a_sr 447 448 // Author: E.Chernyaev (IHEP/Protvino) 449 // Input: scrsize - size of input buffer 450 // src - input buffer 451 // tgtsize - size of target buffer 452 // 453 // Output: tgt - target buffer (decompress 454 // irep - size of decompressed data 455 // 0 - if error 456 457 a_irep = 0; 458 459 // C H E C K H E A D E R 460 const int HDRSIZE = 9; 461 462 if (a_srcsize < HDRSIZE) { 463 a_out << "tools::rroot::key::unzip : too 464 return false; 465 } 466 467 unsigned char DEFLATE = 8; 468 469 if ((a_src[0] != 'C' && a_src[0] != 'Z') | 470 (a_src[1] != 'S' && a_src[1] != 'L') | 471 a_src[2] != DEFLATE) { 472 a_out << "tools::rroot::key::unzip : err 473 return false; 474 } 475 476 long _ibufcnt = (long)a_src[3] | ((long)a_ 477 long isize = (long)a_src[6] | ((long)a_src 478 479 if(a_tgtsize<isize) { 480 a_out << "tools::rroot::key::unzip : too 481 return false; 482 } 483 484 if(_ibufcnt + HDRSIZE != a_srcsize) { 485 a_out << "tools::rroot::key::unzip :" 486 << " discrepancy in source length. 487 return false; 488 } 489 490 // D E C O M P R E S S D A T A 491 492 if (a_src[0] == 'Z' && a_src[1] == 'L') { 493 decompress_func func; 494 if(!a_file.unziper('Z',func)) { 495 a_out << "tools::rroot::key::unzip : " 496 << " zlib unziper not found." << 497 return false; 498 } 499 500 unsigned int irep; 501 char* src = (char*)(a_src + HDRSIZE); 502 if(!func(a_out, 503 (unsigned int)a_srcsize,src, 504 (unsigned int)a_tgtsize,(char*) 505 a_out << "tools::rroot::key::unzip : " 506 << " unzip function failed." << 507 a_irep = 0; 508 return false; 509 } 510 a_irep = irep; 511 512 #ifdef TOOLS_USE_CSZ 513 } else if (a_src[0] == 'C' && a_src[1] == 514 //compressed with Chernyaev & Smirnov 515 516 csz__Init_Inflate(_ibufcnt,a_src + HDRSI 517 518 if (csz__Inflate()) { 519 a_out << "tools::rroot::key::unzip :" 520 << " error during decompression. 521 return false; 522 } 523 524 unsigned char* obufptr = csz__obufptr(); 525 526 // if (obufptr - a_tgt != isize) { 527 // There are some rare cases when a few 528 if (obufptr - a_tgt > a_tgtsize) { 529 a_out << "tools::rroot::key::_unzip :" 530 << " discrepancy " << (int)(obuf 531 << " with initial size: " << (in 532 << ", tgtsize= " << a_tgtsize 533 << std::endl; 534 a_irep = int(obufptr - a_tgt); 535 //return false; 536 } 537 a_irep = isize; 538 539 //a_out << "tools::rroot::key::unzip : C 540 // << a_irep << std::endl; 541 #endif 542 } else { 543 a_out << "tools::rroot::key::_unzip : un 544 << " [0] = " << a_src[0] << ", [1] 545 << std::endl; 546 a_irep = 0; 547 return false; 548 } 549 return true; 550 } 551 552 static const std::string& s_class() { 553 static const std::string s_v("tools::rroot 554 return s_v; 555 } 556 protected: 557 std::ostream& m_out; 558 uint32 m_buf_size; 559 char* m_buffer; 560 // Record (stored in file) : 561 uint32 m_nbytes; //Number of b 562 uint32 m_version; //Key version 563 uint32 m_object_size; //Length of u 564 date m_date; //Date/Time of i 565 uint16 m_key_length; //Number of byt 566 uint16 m_cycle; //Cycle number 567 seek m_seek_key; //Location of ob 568 seek m_seek_parent_dir; //Location of pa 569 std::string m_object_class; //Object Class n 570 std::string m_object_name; //name of the ob 571 std::string m_object_title; //title of the o 572 }; 573 574 }} 575 576 #endif 577 578 //doc : 579 ////////////////////////////////////////////// 580 // 581 // The Key class includes functions to book s 582 // to create I/O buffers, to fill these buff 583 // to compress/uncompress data buffers. 584 // 585 // Before saving (making persistent) an objec 586 // be created. The key structure contains all 587 // uniquely identify a persistent object on a 588 // fNbytes = number of bytes for the co 589 // version of the Key class 590 // fObjlen = Length of uncompressed obj 591 // fDatime = Date/Time when the object 592 // fKeylen = number of bytes for the ke 593 // fCycle = cycle number of the object 594 // fSeekKey = Address of the object on f 595 // This is a redundant inform 596 // the data base integrity. 597 // fSeekPdir = Pointer to the directory s 598 // fClassName = Object class name 599 // fName = name of the object 600 // fTitle = title of the object 601 // 602 // The Key class is used by ROOT to: 603 // - to write an object in the Current Dire 604 // - to write a new ntuple buffer 605 // 606 //////////////////////////////////////////////