Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_rroot_branch 5 #define tools_rroot_branch 6 7 #include "base_leaf" 8 #include "basket" 9 #include "obj_array" 10 #include "seek" 11 #include "ifile" 12 #include "ifac" 13 #include "../mnmx" 14 #include "../forit" 15 #include "../sprintf" 16 #include "dummy" //for TIOFeatures streaming. 17 18 #include <map> 19 20 namespace tools { 21 namespace rroot { 22 23 class branch : public virtual iro { 24 //static uint32 kDoNotProcess() {return (1<<10);} // Active bit for branches 25 public: 26 static const std::string& s_class() { 27 static const std::string s_v("tools::rroot::branch"); 28 return s_v; 29 } 30 public: //iro 31 virtual void* cast(const std::string& a_class) const { 32 if(void* p = cmp_cast<branch>(this,a_class)) return p; 33 return 0; 34 } 35 virtual const std::string& s_cls() const {return s_class();} 36 public: 37 static cid id_class() {return branch_cid();} 38 virtual void* cast(cid a_class) const { 39 if(void* p = cmp_cast<branch>(this,a_class)) {return p;} 40 else return 0; 41 } 42 public: 43 virtual iro* copy() const {return new branch(*this);} 44 virtual bool stream(buffer& a_buffer) { 45 _clear(); 46 //::printf("debug : branch::stream : begin\n"); 47 48 int fCompress; 49 int fBasketSize; 50 //int fNleaves; 51 //uint64 m_entries; 52 53 //uint64 m_tot_bytes; 54 //uint64 m_zip_bytes; 55 int fSplitLevel; 56 uint32 fMaxBaskets; 57 int fOffset; 58 59 unsigned int _s,_c; 60 //FIXME gROOT->SetReadingObject(kTRUE); 61 short vers; 62 if(!a_buffer.read_version(vers,_s,_c)) return false; 63 64 //::printf("debug : branch::stream : version %d count %d\n",vers,c); 65 66 if (vers > 5) { 67 //TBranch::Class()->ReadBuffer(b, this, v, s, c); 68 //gBranch = branchSave; 69 //fDirectory = gDirectory; 70 //fNleaves = m_leaves.GetEntriesFast(); 71 //if (fFileName.Length() != 0) fDirectory = 0; 72 //gROOT->SetReadingObject(kFALSE); 73 //return; 74 } 75 //====process old versions before automatic schema evolution 76 77 {uint32 old = a_buffer.length(); 78 uint32 id; 79 uint32 m_bits; 80 if(!Object_stream(a_buffer,id,m_bits)) return false; 81 a_buffer.set_offset(old);} 82 83 if(!Named_stream(a_buffer,m_name,m_title)) return false; 84 85 //::printf("debug : branch::stream %s %s\n",m_name.c_str(),m_title.c_str()); 86 87 if(vers<=5) { 88 if(!a_buffer.read(fCompress)) return false; 89 if(!a_buffer.read(fBasketSize)) return false; 90 if(!a_buffer.read(fEntryOffsetLen)) return false; 91 if(!a_buffer.read(fMaxBaskets)) return false; 92 if(!a_buffer.read(m_write_basket)) return false; 93 if(!a_buffer.read(m_entry_number)) return false; 94 {double v; 95 if(!a_buffer.read(v)) return false; 96 //m_entries = uint64(v); 97 } 98 {double v; 99 if(!a_buffer.read(v)) return false; 100 //m_tot_bytes = uint64(v); 101 } 102 {double v; 103 if(!a_buffer.read(v)) return false; 104 //m_zip_bytes = uint64(v); 105 } 106 if(!a_buffer.read(fOffset)) return false; 107 108 } else if(vers<=6) { 109 if(!a_buffer.read(fCompress)) return false; 110 if(!a_buffer.read(fBasketSize)) return false; 111 if(!a_buffer.read(fEntryOffsetLen)) return false; 112 if(!a_buffer.read(m_write_basket)) return false; 113 if(!a_buffer.read(m_entry_number)) return false; 114 if(!a_buffer.read(fOffset)) return false; 115 if(!a_buffer.read(fMaxBaskets)) return false; 116 {double v; 117 if(!a_buffer.read(v)) return false; 118 //m_entries = uint64(v); 119 } 120 {double v; 121 if(!a_buffer.read(v)) return false; 122 //m_tot_bytes = uint64(v); 123 } 124 {double v; 125 if(!a_buffer.read(v)) return false; 126 //m_zip_bytes = uint64(v); 127 } 128 129 } else if(vers<=7) { 130 if(!a_buffer.read(fCompress)) return false; 131 if(!a_buffer.read(fBasketSize)) return false; 132 if(!a_buffer.read(fEntryOffsetLen)) return false; 133 if(!a_buffer.read(m_write_basket)) return false; 134 if(!a_buffer.read(m_entry_number)) return false; 135 if(!a_buffer.read(fOffset)) return false; 136 if(!a_buffer.read(fMaxBaskets)) return false; 137 if(!a_buffer.read(fSplitLevel)) return false; 138 {double v; 139 if(!a_buffer.read(v)) return false; 140 //m_entries = uint64(v); 141 } 142 {double v; 143 if(!a_buffer.read(v)) return false; 144 //m_tot_bytes = uint64(v); 145 } 146 {double v; 147 if(!a_buffer.read(v)) return false; 148 //m_zip_bytes = uint64(v); 149 } 150 151 } else if(vers<=9) { 152 {short color,style; 153 if(!AttFill_stream(a_buffer,color,style)) return false;} 154 if(!a_buffer.read(fCompress)) return false; 155 if(!a_buffer.read(fBasketSize)) return false; 156 if(!a_buffer.read(fEntryOffsetLen)) return false; 157 if(!a_buffer.read(m_write_basket)) return false; 158 if(!a_buffer.read(m_entry_number)) return false; 159 if(!a_buffer.read(fOffset)) return false; 160 if(!a_buffer.read(fMaxBaskets)) return false; 161 if(!a_buffer.read(fSplitLevel)) return false; 162 {double v; 163 if(!a_buffer.read(v)) return false; 164 //m_entries = uint64(v); 165 } 166 {double v; 167 if(!a_buffer.read(v)) return false; 168 //m_tot_bytes = uint64(v); 169 } 170 {double v; 171 if(!a_buffer.read(v)) return false; 172 //m_zip_bytes = uint64(v); 173 } 174 175 } else if(vers<=10) { 176 {short color,style; 177 if(!AttFill_stream(a_buffer,color,style)) return false;} 178 179 if(!a_buffer.read(fCompress)) return false; 180 if(!a_buffer.read(fBasketSize)) return false; 181 if(!a_buffer.read(fEntryOffsetLen)) return false; 182 if(!a_buffer.read(m_write_basket)) return false; 183 {uint64 v; 184 if(!a_buffer.read(v)) return false; 185 m_entry_number = uint32(v);} 186 if(!a_buffer.read(fOffset)) return false; 187 if(!a_buffer.read(fMaxBaskets)) return false; 188 if(!a_buffer.read(fSplitLevel)) return false; 189 190 {uint64 v; 191 if(!a_buffer.read(v)) return false; 192 //m_entries = v; 193 } 194 {uint64 v; 195 if(!a_buffer.read(v)) return false; 196 //m_tot_bytes = v; 197 } 198 {uint64 v; 199 if(!a_buffer.read(v)) return false; 200 //m_zip_bytes = v; 201 } 202 203 } else { //vers>=11 204 205 {short color,style; 206 if(!AttFill_stream(a_buffer,color,style)) return false;} 207 208 if(!a_buffer.read(fCompress)) return false; 209 if(!a_buffer.read(fBasketSize)) return false; 210 if(!a_buffer.read(fEntryOffsetLen)) return false; 211 if(!a_buffer.read(m_write_basket)) return false; 212 {uint64 v; 213 if(!a_buffer.read(v)) return false; 214 m_entry_number = uint32(v);} 215 if(vers>=13) { 216 dummy _dummy; 217 if(!_dummy.stream(a_buffer)) { //TIOFeatures fIOFeatures 218 m_out << "tools::rroot::branch::stream : can't read (dummy) TIOFeatures." << std::endl; 219 return false; 220 } 221 } 222 if(!a_buffer.read(fOffset)) return false; 223 if(!a_buffer.read(fMaxBaskets)) return false; 224 if(!a_buffer.read(fSplitLevel)) return false; 225 {uint64 v; 226 if(!a_buffer.read(v)) return false; 227 //m_entries = v; 228 } 229 {uint64 v; 230 if(!a_buffer.read(v)) return false;} //fFirstEntry 231 {uint64 v; 232 if(!a_buffer.read(v)) return false; 233 //m_tot_bytes = v; 234 } 235 {uint64 v; 236 if(!a_buffer.read(v)) return false; 237 //m_zip_bytes = v; 238 } 239 } 240 241 //::printf("debug : branch::stream : %s : fSplitLevel %d\n",m_name.c_str(),fSplitLevel); 242 243 //TObjArray 244 //::printf("debug : branch::stream : branches : begin\n"); 245 {ifac::args args; 246 if(!m_branches.stream(a_buffer,args)) { 247 m_out << "tools::rroot::branch::stream :" 248 << " can't read branches." 249 << std::endl; 250 return false; 251 }} 252 //::printf("debug : branch::stream : branches : end %d\n", 253 // m_branches.size()); 254 255 /* We see that with LHCb files. 256 if(m_entry_number!=m_entries) { 257 m_out << "tools::rroot::branch::stream :" 258 << " for branch " << sout(m_name) << " :" 259 << " WARNING : m_entry_number!=m_entries." 260 << " m_entry_number " << m_entry_number 261 << " m_entries " << m_entries 262 << std::endl; 263 //return false; 264 } 265 */ 266 267 //TObjArray 268 //::printf("debug : branch::stream : leaves : begin\n"); 269 {ifac::args args; 270 //args[ifac::arg_branch()] = this; 271 if(!m_leaves.stream(a_buffer,args)) { 272 m_out << "tools::rroot::branch::stream :" 273 << " can't read leaves." 274 << std::endl; 275 return false; 276 }} 277 //::printf("debug : branch::stream : leaves : end\n"); 278 279 //TObjArray 280 //IMPORTANT : accept_null=true 281 //::printf("debug : branch::stream : streamed_baskets : begin\n"); 282 {ifac::args args; 283 if(!m_streamed_baskets.stream(a_buffer,args,true)) { 284 m_out << "tools::rroot::branch::stream :" 285 << " can't read baskets." 286 << std::endl; 287 return false; 288 }} 289 //::printf("debug : branch::stream : streamed_baskets : end\n"); 290 291 //fNleaves = m_leaves.size(); 292 293 if(fMaxBaskets<=0) { 294 m_out << "tools::rroot::branch::stream :" 295 << " fMaxBaskets null." 296 << std::endl; 297 return false; 298 } 299 300 fBasketEntry = new int[fMaxBaskets]; 301 fBasketBytes = new int[fMaxBaskets]; 302 fBasketSeek = new seek[fMaxBaskets]; 303 {for(uint32 i=0;i<fMaxBaskets;i++) { 304 fBasketEntry[i] = 0; 305 fBasketBytes[i] = 0; 306 fBasketSeek[i] = 0; 307 }} 308 309 if(vers<6) { 310 {uint32 n; 311 if(!a_buffer.read_array<int>(fMaxBaskets,fBasketEntry,n)) { 312 _clear(); 313 return false; 314 }} 315 if(vers<=4) { 316 for (uint32 i=0;i<fMaxBaskets;i++) fBasketBytes[i] = 0; 317 } else { 318 uint32 n; 319 if(!a_buffer.read_array<int>(fMaxBaskets,fBasketBytes,n)) { 320 _clear(); 321 return false; 322 } 323 } 324 if(vers<2) { 325 //GB : comment. 326 //for(int i=0;i<m_write_basket;i++) { 327 // fBasketSeek[i] = getBasket(i)->seekKey(); 328 //} 329 m_out << "tools::rroot::branch::stream :" 330 << " v < 2. Not (yet) handled." 331 << std::endl; 332 _clear(); 333 return false; 334 } else { 335 int n; 336 if(!a_buffer.read(n)) { 337 _clear(); 338 return false; 339 } 340 for(int i=0;i<n;i++) { 341 seek32 _seek; 342 if(!a_buffer.read(_seek)) { 343 _clear(); 344 return false; 345 } 346 fBasketSeek[i] = _seek; 347 } 348 } 349 350 } else if(vers<=9) { 351 // See TStreamerInfo::ReadBuffer::ReadBasicPointer 352 353 //Int_t[fMaxBaskets] 354 {char isArray; 355 if(!a_buffer.read(isArray)) { 356 _clear(); 357 return false; 358 } 359 if(isArray) { 360 if(!a_buffer.read_fast_array<int>(fBasketBytes,fMaxBaskets)) { 361 _clear(); 362 return false; 363 } 364 }} 365 366 //Int_t[fMaxBaskets] 367 {char isArray; 368 if(!a_buffer.read(isArray)) { 369 _clear(); 370 return false; 371 } 372 if(isArray) { 373 if(!a_buffer.read_fast_array<int>(fBasketEntry,fMaxBaskets)) { 374 _clear(); 375 return false; 376 } 377 }} 378 379 //Seek_t[fMaxBaskets] 380 {char isBigFile; 381 if(!a_buffer.read(isBigFile)) { 382 _clear(); 383 return false; 384 } 385 if(isBigFile==2) { 386 if(!a_buffer.read_fast_array<seek>(fBasketSeek,fMaxBaskets)) { 387 _clear(); 388 return false; 389 } 390 } else { 391 for(uint32 i=0;i<fMaxBaskets;i++) { 392 seek32 _seek; 393 if(!a_buffer.read(_seek)) { 394 _clear(); 395 return false; 396 } 397 fBasketSeek[i] = _seek; 398 } 399 }} 400 401 } else { //vers>=10 402 // See TStreamerInfo::ReadBuffer::ReadBasicPointer 403 404 //Int_t[fMaxBaskets] 405 {char isArray; 406 if(!a_buffer.read(isArray)) { 407 _clear(); 408 return false; 409 } 410 if(isArray) { 411 if(!a_buffer.read_fast_array<int>(fBasketBytes,fMaxBaskets)) { 412 _clear(); 413 return false; 414 } 415 }} 416 417 //Long64_t[fMaxBaskets] 418 {char isArray; 419 if(!a_buffer.read(isArray)) { 420 _clear(); 421 return false; 422 } 423 if(isArray) { 424 uint64* v = new uint64[fMaxBaskets]; 425 if(!a_buffer.read_fast_array<uint64>(v,fMaxBaskets)) { 426 _clear(); 427 return false; 428 } 429 for(uint32 i=0;i<fMaxBaskets;i++) fBasketEntry[i] = int(v[i]); 430 delete [] v; 431 }} 432 433 //Long64_t[fMaxBaskets] 434 {char isArray; 435 if(!a_buffer.read(isArray)) { 436 _clear(); 437 return false; 438 } 439 if(isArray) { 440 uint64* v = new uint64[fMaxBaskets]; 441 if(!a_buffer.read_fast_array<uint64>(v,fMaxBaskets)) { 442 _clear(); 443 return false; 444 } 445 for(uint32 i=0;i<fMaxBaskets;i++) fBasketSeek[i] = v[i]; 446 delete [] v; 447 }} 448 } 449 450 if(vers>2) { 451 //TString 452 std::string fileName; 453 if(!a_buffer.read(fileName)) { 454 _clear(); 455 return false; 456 } 457 } 458 459 //FIXME if(vers<4) SetAutoDelete(kTRUE); 460 //FIXME gROOT->SetReadingObject(kFALSE); 461 if(!a_buffer.check_byte_count(_s, _c,"TBranch")) { 462 _clear(); 463 return false; 464 } 465 466 //GB : analyse fBasketEntry. 467 m_first_last.clear(); 468 {// There are (m_write_basket+1) sensitive elements in fBasketEntry : 469 // (Do we have to check that ?) 470 for(uint32 i=0;i<m_write_basket;i++) { 471 uint64 first = fBasketEntry[i]; 472 uint64 last = fBasketEntry[i+1]-1; 473 m_first_last.push_back(std::pair<uint64,uint64>(first,last)); 474 } 475 if(m_entry_number) { 476 uint64 first = fBasketEntry[m_write_basket]; 477 uint64 last = m_entry_number-1; 478 m_first_last.push_back(std::pair<uint64,uint64>(first,last)); 479 }} 480 //_dump_first_last(); 481 482 //GB : analyse fBasketSeek : 483 {uint32 num = 0; 484 uint32 mxi = 0; 485 for(uint32 i=0;i<fMaxBaskets;i++) { 486 if(!fBasketSeek[i]) continue; 487 num++; 488 mxi = mx<uint32>(i,mxi); 489 } 490 if(m_write_basket) { 491 if((num!=m_write_basket)||(mxi!=(m_write_basket-1))) { 492 m_out << "tools::rroot::branch::stream :" 493 << " fBasketSeek[] inconsistent with m_write_basket." 494 << " m_write_basket " << m_write_basket 495 << " num " << num 496 << " mxi " << mxi 497 << std::endl; 498 _clear(); 499 return false; 500 } 501 }} 502 503 //GB : analyse m_streamed_baskets : 504 {int index = 0; 505 tools_vforcit(basket*,m_streamed_baskets,it) { 506 if(*it) { 507 if(!(*it)->buf()||!(*it)->buf_size()) { 508 m_out << "tools::rroot::branch::stream :" 509 << " expect a basket with a not empty buffer." 510 << std::endl; 511 return false; 512 } 513 //in the below, false is to say m_baskets is not owner of *it. 514 m_baskets[index] = std::pair<basket*,bool>(*it,false); 515 } 516 index++; 517 }} 518 519 return true; 520 } 521 522 public: 523 //virtual for branch_element 524 525 virtual bool read_leaves(ifile&,buffer& a_buffer){ 526 tools_vforcit(base_leaf*,m_leaves,it) { 527 if(!(*it)->read_buffer(a_buffer)) { 528 m_out << "tools::rroot::branch::read_leaves :" 529 << " read_buffer failed." 530 << std::endl; 531 return false; 532 } 533 } 534 return true; 535 } 536 537 virtual bool find_entry(ifile& a_file,uint64 a_entry,uint32& a_nbytes){ 538 // Read all leaves of entry and return total number of bytes : 539 // The input argument entry is the entry serial number in the current tree. 540 a_nbytes = 0; 541 //if(_test_bit(kDoNotProcess())) return true; 542 543 //if(fReadEntry == (int)a_entry) return true; 544 if(a_entry>=m_entry_number) { 545 //m_out << "tools::rroot::branch::find_entry :" 546 // << " for branch " << sout(m_name) << " :" 547 // << " a_entry not within [0," << m_entry_number << "[." 548 // << std::endl; 549 //return false; 550 return true; //CERN-ROOT does not consider it is an error. 551 } 552 if(!m_entry_number || m_first_last.empty() ) { //GB 553 m_out << "tools::rroot::branch::find_entry :" 554 << " nothing to read." 555 << std::endl; 556 return false; //nothing to read. 557 } 558 559 if(m_read_basket>=m_first_last.size()) { 560 m_out << "tools::rroot::branch::find_entry :" 561 << " bad m_first_last access." 562 << std::endl; 563 return false; 564 } 565 566 uint64 first = m_first_last[m_read_basket].first; 567 uint64 last = m_first_last[m_read_basket].second; 568 569 // Are we still in the same ReadBasket? 570 if((a_entry<first)||(a_entry>last)) { 571 m__read_basket = 0; 572 uint32 old_read_basket = m_read_basket; 573 574 //look first in the next basket window : 575 bool found = false; 576 if((m_read_basket+1)<m_first_last.size()) { 577 first = m_first_last[m_read_basket+1].first; 578 last = m_first_last[m_read_basket+1].second; 579 if((a_entry>=first)&&(a_entry<=last)) { 580 m_read_basket++; 581 found = true; 582 } 583 } 584 if(!found) { 585 uint32 count = 0; 586 typedef std::pair<uint64,uint64> first_last; 587 tools_vforcit(first_last,m_first_last,it) { 588 first = (*it).first; 589 last = (*it).second; 590 if((a_entry>=first)&&(a_entry<=last)) { 591 m_read_basket = count; 592 found = true; 593 break; 594 } 595 count++; 596 } 597 } 598 if(!found) { //something weird in fBasketEntry. 599 m_out << "tools::rroot::branch::find_entry :" 600 << " fancy fBasketEntry." 601 << std::endl; 602 return false; 603 } else { 604 // if found, erase m_baskets[old_read_basket] to avoid 605 // having all data in memory ! 606 std::map<uint32, std::pair<basket*,bool> >::iterator it = m_baskets.find(old_read_basket); 607 if(it!=m_baskets.end()) { 608 if((*it).second.second) { 609 basket* bsk = (*it).second.first; 610 m_baskets.erase(it); 611 delete bsk; 612 //::printf("debug : erase basket %d\n",old_read_basket); 613 } 614 } 615 } 616 } 617 618 if(!m__read_basket) { 619 620 basket* bsk = 0; 621 std::map<uint32, std::pair<basket*,bool> >::iterator it = m_baskets.find(m_read_basket); 622 if(it!=m_baskets.end()) { 623 bsk = (*it).second.first; 624 } else { 625 if(m_read_basket>=m_write_basket) { 626 m_out << "tools::rroot::branch::find_entry :" 627 << " basket lacking !" 628 << " wanting index " << m_read_basket 629 << ". fBasketSeek entries " << m_write_basket 630 << std::endl; 631 return false; 632 } 633 if(!fBasketSeek[m_read_basket]) { 634 m_out << "tools::rroot::branch::find_entry :" 635 << " fBasketSeek is null for index " << m_read_basket 636 << std::endl; 637 return false; 638 } 639 if(!fBasketBytes[m_read_basket]) { 640 m_out << "tools::rroot::branch::find_entry :" 641 << " fBasketBytes is null for index " << m_read_basket 642 << std::endl; 643 return false; 644 } 645 646 bsk = get_basket(a_file,fBasketSeek[m_read_basket],fBasketBytes[m_read_basket]); 647 if(!bsk) { 648 m_out << "tools::rroot::branch::find_entry :" 649 << " can't read basket " << m_read_basket 650 << " at file pos " << fBasketSeek[m_read_basket] 651 << " and size " << fBasketBytes[m_read_basket] 652 << std::endl; 653 return false; 654 } 655 656 //m_out << "tools::rroot::branch::find_entry :" 657 // << " got basket " << m_read_basket 658 // << " of size " << fBasketBytes[m_read_basket] 659 // << std::endl; 660 661 m_baskets[m_read_basket] = std::pair<basket*,bool>(bsk,true); 662 } 663 664 m__read_basket = bsk; 665 } 666 667 // Set entry offset in buffer and read data from all leaves 668 //buf->resetMap(); 669 670 uint32 bufbegin; 671 {int* entry_offset = m__read_basket->entry_offset(); 672 if(entry_offset) { 673 uint32 index = uint32(a_entry-first); 674 if(index>=m__read_basket->nev()) { 675 m_out << "tools::rroot::branch::find_entry :" 676 << " can't access entry offset " << index 677 << ". nev " << m__read_basket->nev() 678 << std::endl; 679 return false; 680 } 681 bufbegin = entry_offset[index]; 682 //::printf("debug : xxx++ %u : %u\n",index,bufbegin); 683 } else { 684 bufbegin = (uint32)(m__read_basket->key_length() + (a_entry-first)*m__read_basket->nev_buf_size()); 685 }} 686 687 {int* displacement = m__read_basket->displacement(); 688 if(displacement) { 689 m_out << "tools::rroot::branch::find_entry :" 690 << " not null displacement. Not yet handled." 691 << std::endl; 692 //buf->setDisplacement(displacement[a_entry-first]); 693 } else { 694 //buf->setDisplacement(); 695 }} 696 697 /* 698 if(bufbegin>=m__read_basket->buf_size()) { 699 m_out << "tools::rroot::branch::find_entry :" 700 << " bad buffer access for entry " << a_entry 701 << ". bufbegin " << bufbegin 702 << ", buf_size " << basket->buf_size() 703 << ", (entry-first) " << (a_entry-first) 704 << std::endl; 705 {int* entry_offset = m__read_basket->entry_offset(); 706 if(entry_offset) { 707 uint32 nev = m__read_basket->nev(); 708 ::printf("debug : eoff : num %d\n",nev); 709 for(uint32 i=0;i<nev;i++){ 710 ::printf("debug : eoff %d : %d\n",i,entry_offset[i]); 711 } 712 }} 713 return false; 714 } 715 */ 716 717 buffer _buffer(m_out,a_file.byte_swap(),m__read_basket->buf_size(),m__read_basket->buf(),0,false); 718 _buffer.set_offset(bufbegin); 719 _buffer.set_map_objs(true); //for MEMPHYS/applications/read.icc 720 721 if(!read_leaves(a_file,_buffer)) { 722 m_out << "tools::rroot::branch::find_entry :" 723 << " can't read leaves for entry " << a_entry 724 << ". read_basket was " << m_read_basket 725 << ", first " << first 726 << ", last " << last 727 << "." 728 << std::endl; 729 return false; 730 } 731 732 //fReadEntry = a_entry; 733 734 a_nbytes = _buffer.length() - bufbegin; 735 736 return true; 737 } 738 739 virtual bool show(std::ostream& a_out,ifile& a_file,uint64 a_entry) { 740 // Print values of all active leaves for entry : 741 // if entry==-1, print current entry (default) 742 uint32 n; 743 if(!find_entry(a_file,a_entry,n)) return false; 744 745 tools_vforcit(base_leaf*,m_leaves,it) { 746 base_leaf* bl = *it; 747 748 uint32 num = bl->num_elem(); 749 num = mn<uint32>(num,10); 750 if(!num) continue; 751 752 {std::string _s; 753 uint32 len = uint32(bl->name().size())+128; 754 sprintf(_s,len," %-15s = ",bl->name().c_str()); 755 a_out << _s;} 756 757 for(uint32 i=0;i<num;i++) { 758 if(i) a_out << ", "; 759 bl->print_value(a_out,i); 760 } 761 762 a_out << std::endl; 763 } 764 765 return true; 766 } 767 public: 768 branch(std::ostream& a_out,ifac& a_fac) 769 :m_out(a_out) 770 ,m_fac(a_fac) 771 772 ,m_streamed_baskets(m_fac) 773 ,m__read_basket(0) 774 775 //,m_bits(0) 776 ,m_name("") 777 ,m_title("") 778 ,fAutoDelete(false) 779 780 ,m_branches(m_fac) 781 ,m_leaves(m_fac) 782 783 ,fEntryOffsetLen(0) 784 ,m_write_basket(0) 785 ,m_entry_number(0) 786 ,m_read_basket(0) 787 ,fBasketBytes(0) 788 ,fBasketEntry(0) 789 ,fBasketSeek(0) 790 { 791 #ifdef TOOLS_MEM 792 mem::increment(s_class().c_str()); 793 #endif 794 } 795 virtual ~branch(){ 796 _clear(); 797 #ifdef TOOLS_MEM 798 mem::decrement(s_class().c_str()); 799 #endif 800 } 801 protected: 802 branch(const branch& a_from) 803 :iro(a_from) 804 ,m_out(a_from.m_out),m_fac(a_from.m_fac) 805 ,m_streamed_baskets(m_fac) 806 ,m__read_basket(0) 807 ,fAutoDelete(false) 808 ,m_branches(m_fac) 809 ,m_leaves(m_fac) 810 ,fEntryOffsetLen(1000) 811 ,m_write_basket(0) 812 ,m_entry_number(0) 813 ,m_read_basket(0) 814 ,fBasketBytes(0) 815 ,fBasketEntry(0) 816 ,fBasketSeek(0) 817 {} 818 branch& operator=(const branch&){return *this;} 819 public: 820 uint32 entry_number() const {return m_entry_number;} 821 const std::string& name() const {return m_name;} 822 const std::string& title() const {return m_title;} 823 const std::vector<base_leaf*>& leaves() const {return m_leaves;} 824 const std::vector<branch*>& branches() const {return m_branches;} 825 protected: 826 basket* get_basket(ifile& a_file,seek a_pos,uint32 a_len) { 827 //if(fBranch.tree().memoryFull(fBufferSize)) fBranch.dropBaskets(); 828 if(!a_len) return 0; 829 830 basket* _basket = new basket(m_out,a_pos,a_len); //basket is a key. 831 if(!_basket->read_file(a_file)) { 832 m_out << "tools::rroot::branch::get_basket :" 833 << " read_file() failed." 834 << std::endl; 835 delete _basket; 836 return 0; 837 } 838 {buffer _buffer(m_out,a_file.byte_swap(),a_len,_basket->buf(),0,false); 839 if(!_basket->stream(_buffer)) { 840 m_out << "tools::rroot::branch::get_basket :" 841 << " basket stream failed." 842 << std::endl; 843 delete _basket; 844 return 0; 845 }} 846 unsigned int sz; 847 char* buf = _basket->get_object_buffer(a_file,sz); //basket owns buf. 848 if(!buf) { 849 m_out << "tools::rroot::branch::get_basket :" 850 << " get_object_buffer() failed." 851 << std::endl; 852 delete _basket; 853 return 0; 854 } 855 856 if(_basket->seek_key()!=a_pos) { //consistency check. 857 m_out << "tools::rroot::branch::get_basket :" 858 << " seek anomaly." 859 << " a_pos " << a_pos 860 << " seek_key() " << _basket->seek_key() 861 << std::endl; 862 delete _basket; 863 return 0; 864 } 865 //if(_basket->nbytes()!=a_len) { //consistency check. 866 // m_out << "tools::rroot::branch::get_basket :" 867 // << " WARNING : length anomaly." 868 // << " a_len " << a_len 869 // << " nbytes() " << _basket->nbytes() 870 // << std::endl; 871 //} 872 873 if(fEntryOffsetLen) { 874 if(!_basket->read_offset_tables(a_file.byte_swap())) { 875 m_out << "tools::rroot::branch::get_basket :" 876 << " read_offset_tables failed." 877 << std::endl; 878 delete _basket; 879 return 0; 880 }} 881 882 return _basket; 883 } 884 protected: 885 void _clear() { 886 delete [] fBasketEntry; 887 delete [] fBasketBytes; 888 delete [] fBasketSeek; 889 fBasketEntry = 0; 890 fBasketBytes = 0; 891 fBasketSeek = 0; 892 893 {typedef std::pair<basket*,bool> basket_todel; 894 tools_mforit(uint32,basket_todel,m_baskets,it) { 895 if((*it).second.second) delete (*it).second.first; 896 } 897 m_baskets.clear();} 898 899 m_branches.cleanup(); 900 m_leaves.cleanup(); 901 m_streamed_baskets.cleanup(); 902 } 903 904 void _dump_first_last() { 905 m_out << "tools::rroot::branch::_dump_first_last :" 906 << " first_last " << m_first_last.size() 907 << std::endl; 908 typedef std::pair<uint64,uint64> first_last; 909 tools_vforcit(first_last,m_first_last,it) { 910 uint64 first = (*it).first; 911 uint64 last = (*it).second; 912 m_out << "tools::rroot::branch::stream :" 913 << " first " << first 914 << " last " << last 915 << std::endl; 916 } 917 } 918 919 //bool _test_bit(uint32 a_f) const { 920 // return (bool)(m_bits & a_f); 921 //} 922 923 924 protected: 925 std::ostream& m_out; 926 ifac& m_fac; 927 std::vector< std::pair<uint64,uint64> > m_first_last; 928 std::map<uint32, std::pair<basket*,bool> > m_baskets; 929 obj_array<basket> m_streamed_baskets; 930 basket* m__read_basket; //optimization 931 protected: 932 //Object 933 //uint32 m_bits; 934 //Named 935 std::string m_name; 936 std::string m_title; 937 938 bool fAutoDelete; 939 obj_array<branch> m_branches; 940 obj_array<base_leaf> m_leaves; 941 uint32 fEntryOffsetLen; // Initial Length of fEntryOffset table in the basket buffers 942 uint32 m_write_basket; // Last basket number written 943 uint32 m_entry_number; // Current entry number (last one filled in this branch) 944 uint32 m_read_basket; //! Current basket number when reading 945 int* fBasketBytes; //[fMaxBaskets] Length of baskets on file 946 int* fBasketEntry; //[fMaxBaskets] Table of first entry in eack basket 947 seek* fBasketSeek; //[fMaxBaskets] Addresses of baskets on file 948 }; 949 950 }} 951 952 #endif