Warning, /include/Geant4/tools/rroot/branch 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_branch
0005 #define tools_rroot_branch
0006
0007 #include "base_leaf"
0008 #include "basket"
0009 #include "obj_array"
0010 #include "seek"
0011 #include "ifile"
0012 #include "ifac"
0013 #include "../mnmx"
0014 #include "../forit"
0015 #include "../sprintf"
0016 #include "dummy" //for TIOFeatures streaming.
0017
0018 #include <map>
0019
0020 namespace tools {
0021 namespace rroot {
0022
0023 class branch : public virtual iro {
0024 public:
0025 static const std::string& s_class() {
0026 static const std::string s_v("tools::rroot::branch");
0027 return s_v;
0028 }
0029 public: //iro
0030 virtual void* cast(const std::string& a_class) const {
0031 if(void* p = cmp_cast<branch>(this,a_class)) return p;
0032 return 0;
0033 }
0034 virtual const std::string& s_cls() const {return s_class();}
0035 public:
0036 static cid id_class() {return branch_cid();}
0037 virtual void* cast(cid a_class) const {
0038 if(void* p = cmp_cast<branch>(this,a_class)) {return p;}
0039 else return 0;
0040 }
0041 public:
0042 virtual iro* copy() const {return new branch(*this);}
0043 virtual bool stream(buffer& a_buffer) {
0044 _clear();
0045
0046 int fCompress;
0047 int fBasketSize;
0048 int fSplitLevel;
0049 uint32 fMaxBaskets;
0050 int fOffset;
0051
0052 unsigned int _s,_c;
0053 short vers;
0054 if(!a_buffer.read_version(vers,_s,_c)) return false;
0055
0056 if (vers > 5) {
0057 }
0058 //====process old versions before automatic schema evolution
0059
0060 {uint32 old = a_buffer.length();
0061 uint32 id;
0062 uint32 m_bits;
0063 if(!Object_stream(a_buffer,id,m_bits)) return false;
0064 a_buffer.set_offset(old);}
0065
0066 if(!Named_stream(a_buffer,m_name,m_title)) return false;
0067
0068
0069 if(vers<=5) {
0070 if(!a_buffer.read(fCompress)) return false;
0071 if(!a_buffer.read(fBasketSize)) return false;
0072 if(!a_buffer.read(fEntryOffsetLen)) return false;
0073 if(!a_buffer.read(fMaxBaskets)) return false;
0074 if(!a_buffer.read(m_write_basket)) return false;
0075 if(!a_buffer.read(m_entry_number)) return false;
0076 {double v;
0077 if(!a_buffer.read(v)) return false;
0078 }
0079 {double v;
0080 if(!a_buffer.read(v)) return false;
0081 }
0082 {double v;
0083 if(!a_buffer.read(v)) return false;
0084 }
0085 if(!a_buffer.read(fOffset)) return false;
0086
0087 } else if(vers<=6) {
0088 if(!a_buffer.read(fCompress)) return false;
0089 if(!a_buffer.read(fBasketSize)) return false;
0090 if(!a_buffer.read(fEntryOffsetLen)) return false;
0091 if(!a_buffer.read(m_write_basket)) return false;
0092 if(!a_buffer.read(m_entry_number)) return false;
0093 if(!a_buffer.read(fOffset)) return false;
0094 if(!a_buffer.read(fMaxBaskets)) return false;
0095 {double v;
0096 if(!a_buffer.read(v)) return false;
0097 }
0098 {double v;
0099 if(!a_buffer.read(v)) return false;
0100 }
0101 {double v;
0102 if(!a_buffer.read(v)) return false;
0103 }
0104
0105 } else if(vers<=7) {
0106 if(!a_buffer.read(fCompress)) return false;
0107 if(!a_buffer.read(fBasketSize)) return false;
0108 if(!a_buffer.read(fEntryOffsetLen)) return false;
0109 if(!a_buffer.read(m_write_basket)) return false;
0110 if(!a_buffer.read(m_entry_number)) return false;
0111 if(!a_buffer.read(fOffset)) return false;
0112 if(!a_buffer.read(fMaxBaskets)) return false;
0113 if(!a_buffer.read(fSplitLevel)) return false;
0114 {double v;
0115 if(!a_buffer.read(v)) return false;
0116 }
0117 {double v;
0118 if(!a_buffer.read(v)) return false;
0119 }
0120 {double v;
0121 if(!a_buffer.read(v)) return false;
0122 }
0123
0124 } else if(vers<=9) {
0125 {short color,style;
0126 if(!AttFill_stream(a_buffer,color,style)) return false;}
0127 if(!a_buffer.read(fCompress)) return false;
0128 if(!a_buffer.read(fBasketSize)) return false;
0129 if(!a_buffer.read(fEntryOffsetLen)) return false;
0130 if(!a_buffer.read(m_write_basket)) return false;
0131 if(!a_buffer.read(m_entry_number)) return false;
0132 if(!a_buffer.read(fOffset)) return false;
0133 if(!a_buffer.read(fMaxBaskets)) return false;
0134 if(!a_buffer.read(fSplitLevel)) return false;
0135 {double v;
0136 if(!a_buffer.read(v)) return false;
0137 }
0138 {double v;
0139 if(!a_buffer.read(v)) return false;
0140 }
0141 {double v;
0142 if(!a_buffer.read(v)) return false;
0143 }
0144
0145 } else if(vers<=10) {
0146 {short color,style;
0147 if(!AttFill_stream(a_buffer,color,style)) return false;}
0148
0149 if(!a_buffer.read(fCompress)) return false;
0150 if(!a_buffer.read(fBasketSize)) return false;
0151 if(!a_buffer.read(fEntryOffsetLen)) return false;
0152 if(!a_buffer.read(m_write_basket)) return false;
0153 {uint64 v;
0154 if(!a_buffer.read(v)) return false;
0155 m_entry_number = uint32(v);}
0156 if(!a_buffer.read(fOffset)) return false;
0157 if(!a_buffer.read(fMaxBaskets)) return false;
0158 if(!a_buffer.read(fSplitLevel)) return false;
0159
0160 {uint64 v;
0161 if(!a_buffer.read(v)) return false;
0162 }
0163 {uint64 v;
0164 if(!a_buffer.read(v)) return false;
0165 }
0166 {uint64 v;
0167 if(!a_buffer.read(v)) return false;
0168 }
0169
0170 } else { //vers>=11
0171
0172 {short color,style;
0173 if(!AttFill_stream(a_buffer,color,style)) return false;}
0174
0175 if(!a_buffer.read(fCompress)) return false;
0176 if(!a_buffer.read(fBasketSize)) return false;
0177 if(!a_buffer.read(fEntryOffsetLen)) return false;
0178 if(!a_buffer.read(m_write_basket)) return false;
0179 {uint64 v;
0180 if(!a_buffer.read(v)) return false;
0181 m_entry_number = uint32(v);}
0182 if(vers>=13) {
0183 dummy _dummy;
0184 if(!_dummy.stream(a_buffer)) { //TIOFeatures fIOFeatures
0185 m_out << "tools::rroot::branch::stream : can't read (dummy) TIOFeatures." << std::endl;
0186 return false;
0187 }
0188 }
0189 if(!a_buffer.read(fOffset)) return false;
0190 if(!a_buffer.read(fMaxBaskets)) return false;
0191 if(!a_buffer.read(fSplitLevel)) return false;
0192 {uint64 v;
0193 if(!a_buffer.read(v)) return false;
0194 }
0195 {uint64 v;
0196 if(!a_buffer.read(v)) return false;} //fFirstEntry
0197 {uint64 v;
0198 if(!a_buffer.read(v)) return false;
0199 }
0200 {uint64 v;
0201 if(!a_buffer.read(v)) return false;
0202 }
0203 }
0204
0205 //TObjArray
0206 {ifac::args args;
0207 if(!m_branches.stream(a_buffer,args)) {
0208 m_out << "tools::rroot::branch::stream :"
0209 << " can't read branches."
0210 << std::endl;
0211 return false;
0212 }}
0213
0214 //TObjArray
0215 {ifac::args args;
0216 if(!m_leaves.stream(a_buffer,args)) {
0217 m_out << "tools::rroot::branch::stream :"
0218 << " can't read leaves."
0219 << std::endl;
0220 return false;
0221 }}
0222
0223 //TObjArray
0224 //IMPORTANT : accept_null=true
0225 {ifac::args args;
0226 if(!m_streamed_baskets.stream(a_buffer,args,true)) {
0227 m_out << "tools::rroot::branch::stream :"
0228 << " can't read baskets."
0229 << std::endl;
0230 return false;
0231 }}
0232
0233 if(fMaxBaskets<=0) {
0234 m_out << "tools::rroot::branch::stream :"
0235 << " fMaxBaskets null."
0236 << std::endl;
0237 return false;
0238 }
0239
0240 fBasketEntry = new int[fMaxBaskets];
0241 fBasketBytes = new int[fMaxBaskets];
0242 fBasketSeek = new seek[fMaxBaskets];
0243 {for(uint32 i=0;i<fMaxBaskets;i++) {
0244 fBasketEntry[i] = 0;
0245 fBasketBytes[i] = 0;
0246 fBasketSeek[i] = 0;
0247 }}
0248
0249 if(vers<6) {
0250 {uint32 n;
0251 if(!a_buffer.read_array<int>(fMaxBaskets,fBasketEntry,n)) {
0252 _clear();
0253 return false;
0254 }}
0255 if(vers<=4) {
0256 for (uint32 i=0;i<fMaxBaskets;i++) fBasketBytes[i] = 0;
0257 } else {
0258 uint32 n;
0259 if(!a_buffer.read_array<int>(fMaxBaskets,fBasketBytes,n)) {
0260 _clear();
0261 return false;
0262 }
0263 }
0264 if(vers<2) {
0265 m_out << "tools::rroot::branch::stream :"
0266 << " v < 2. Not (yet) handled."
0267 << std::endl;
0268 _clear();
0269 return false;
0270 } else {
0271 int n;
0272 if(!a_buffer.read(n)) {
0273 _clear();
0274 return false;
0275 }
0276 for(int i=0;i<n;i++) {
0277 seek32 _seek;
0278 if(!a_buffer.read(_seek)) {
0279 _clear();
0280 return false;
0281 }
0282 fBasketSeek[i] = _seek;
0283 }
0284 }
0285
0286 } else if(vers<=9) {
0287 // See TStreamerInfo::ReadBuffer::ReadBasicPointer
0288 {char isArray;
0289 if(!a_buffer.read(isArray)) {
0290 _clear();
0291 return false;
0292 }
0293 if(isArray) {
0294 if(!a_buffer.read_fast_array<int>(fBasketBytes,fMaxBaskets)) {
0295 _clear();
0296 return false;
0297 }
0298 }}
0299
0300 {char isArray;
0301 if(!a_buffer.read(isArray)) {
0302 _clear();
0303 return false;
0304 }
0305 if(isArray) {
0306 if(!a_buffer.read_fast_array<int>(fBasketEntry,fMaxBaskets)) {
0307 _clear();
0308 return false;
0309 }
0310 }}
0311
0312 {char isBigFile;
0313 if(!a_buffer.read(isBigFile)) {
0314 _clear();
0315 return false;
0316 }
0317 if(isBigFile==2) {
0318 if(!a_buffer.read_fast_array<seek>(fBasketSeek,fMaxBaskets)) {
0319 _clear();
0320 return false;
0321 }
0322 } else {
0323 for(uint32 i=0;i<fMaxBaskets;i++) {
0324 seek32 _seek;
0325 if(!a_buffer.read(_seek)) {
0326 _clear();
0327 return false;
0328 }
0329 fBasketSeek[i] = _seek;
0330 }
0331 }}
0332
0333 } else { //vers>=10
0334 // See TStreamerInfo::ReadBuffer::ReadBasicPointer
0335 {char isArray;
0336 if(!a_buffer.read(isArray)) {
0337 _clear();
0338 return false;
0339 }
0340 if(isArray) {
0341 if(!a_buffer.read_fast_array<int>(fBasketBytes,fMaxBaskets)) {
0342 _clear();
0343 return false;
0344 }
0345 }}
0346
0347 {char isArray;
0348 if(!a_buffer.read(isArray)) {
0349 _clear();
0350 return false;
0351 }
0352 if(isArray) {
0353 uint64* v = new uint64[fMaxBaskets];
0354 if(!a_buffer.read_fast_array<uint64>(v,fMaxBaskets)) {
0355 _clear();
0356 return false;
0357 }
0358 for(uint32 i=0;i<fMaxBaskets;i++) fBasketEntry[i] = int(v[i]);
0359 delete [] v;
0360 }}
0361
0362 {char isArray;
0363 if(!a_buffer.read(isArray)) {
0364 _clear();
0365 return false;
0366 }
0367 if(isArray) {
0368 uint64* v = new uint64[fMaxBaskets];
0369 if(!a_buffer.read_fast_array<uint64>(v,fMaxBaskets)) {
0370 _clear();
0371 return false;
0372 }
0373 for(uint32 i=0;i<fMaxBaskets;i++) fBasketSeek[i] = v[i];
0374 delete [] v;
0375 }}
0376 }
0377
0378 if(vers>2) {
0379 //TString
0380 std::string fileName;
0381 if(!a_buffer.read(fileName)) {
0382 _clear();
0383 return false;
0384 }
0385 }
0386
0387 //FIXME if(vers<4) SetAutoDelete(kTRUE);
0388 //FIXME gROOT->SetReadingObject(kFALSE);
0389 if(!a_buffer.check_byte_count(_s, _c,"TBranch")) {
0390 _clear();
0391 return false;
0392 }
0393
0394 //GB : analyse fBasketEntry.
0395 m_first_last.clear();
0396 {// There are (m_write_basket+1) sensitive elements in fBasketEntry :
0397 // (Do we have to check that ?)
0398 for(uint32 i=0;i<m_write_basket;i++) {
0399 uint64 first = fBasketEntry[i];
0400 uint64 last = fBasketEntry[i+1]-1;
0401 m_first_last.push_back(std::pair<uint64,uint64>(first,last));
0402 }
0403 if(m_entry_number) {
0404 uint64 first = fBasketEntry[m_write_basket];
0405 uint64 last = m_entry_number-1;
0406 m_first_last.push_back(std::pair<uint64,uint64>(first,last));
0407 }}
0408 //_dump_first_last();
0409
0410 //GB : analyse fBasketSeek :
0411 {uint32 num = 0;
0412 uint32 mxi = 0;
0413 for(uint32 i=0;i<fMaxBaskets;i++) {
0414 if(!fBasketSeek[i]) continue;
0415 num++;
0416 mxi = max_of<uint32>(i,mxi);
0417 }
0418 if(m_write_basket) {
0419 if((num!=m_write_basket)||(mxi!=(m_write_basket-1))) {
0420 m_out << "tools::rroot::branch::stream :"
0421 << " fBasketSeek[] inconsistent with m_write_basket."
0422 << " m_write_basket " << m_write_basket
0423 << " num " << num
0424 << " mxi " << mxi
0425 << std::endl;
0426 _clear();
0427 return false;
0428 }
0429 }}
0430
0431 //GB : analyse m_streamed_baskets :
0432 {int index = 0;
0433 tools_vforcit(basket*,m_streamed_baskets,it) {
0434 if(*it) {
0435 if(!(*it)->buf()||!(*it)->buf_size()) {
0436 m_out << "tools::rroot::branch::stream :"
0437 << " expect a basket with a not empty buffer."
0438 << std::endl;
0439 return false;
0440 }
0441 //in the below, false is to say m_baskets is not owner of *it.
0442 m_baskets[index] = std::pair<basket*,bool>(*it,false);
0443 }
0444 index++;
0445 }}
0446
0447 return true;
0448 }
0449
0450 public:
0451 //virtual for branch_element
0452
0453 virtual bool read_leaves(ifile&,buffer& a_buffer){
0454 tools_vforcit(base_leaf*,m_leaves,it) {
0455 if(!(*it)->read_buffer(a_buffer)) {
0456 m_out << "tools::rroot::branch::read_leaves :"
0457 << " read_buffer failed."
0458 << std::endl;
0459 return false;
0460 }
0461 }
0462 return true;
0463 }
0464
0465 virtual bool find_entry(ifile& a_file,uint64 a_entry,uint32& a_nbytes){
0466 // Read all leaves of entry and return total number of bytes :
0467 // The input argument entry is the entry serial number in the current tree.
0468 a_nbytes = 0;
0469 if(a_entry>=m_entry_number) {
0470 return true; //CERN-ROOT does not consider it is an error.
0471 }
0472 if(!m_entry_number || m_first_last.empty() ) { //GB
0473 m_out << "tools::rroot::branch::find_entry :"
0474 << " nothing to read."
0475 << std::endl;
0476 return false; //nothing to read.
0477 }
0478
0479 if(m_read_basket>=m_first_last.size()) {
0480 m_out << "tools::rroot::branch::find_entry :"
0481 << " bad m_first_last access."
0482 << std::endl;
0483 return false;
0484 }
0485
0486 uint64 first = m_first_last[m_read_basket].first;
0487 uint64 last = m_first_last[m_read_basket].second;
0488
0489 // Are we still in the same ReadBasket?
0490 if((a_entry<first)||(a_entry>last)) {
0491 m__read_basket = 0;
0492 uint32 old_read_basket = m_read_basket;
0493
0494 //look first in the next basket window :
0495 bool found = false;
0496 if((m_read_basket+1)<m_first_last.size()) {
0497 first = m_first_last[m_read_basket+1].first;
0498 last = m_first_last[m_read_basket+1].second;
0499 if((a_entry>=first)&&(a_entry<=last)) {
0500 m_read_basket++;
0501 found = true;
0502 }
0503 }
0504 if(!found) {
0505 uint32 count = 0;
0506 for(auto it = m_first_last.cbegin(); it != m_first_last.cend(); ++it) {
0507 first = (*it).first;
0508 last = (*it).second;
0509 if((a_entry>=first)&&(a_entry<=last)) {
0510 m_read_basket = count;
0511 found = true;
0512 break;
0513 }
0514 count++;
0515 }
0516 }
0517 if(!found) { //something weird in fBasketEntry.
0518 m_out << "tools::rroot::branch::find_entry :"
0519 << " fancy fBasketEntry."
0520 << std::endl;
0521 return false;
0522 } else {
0523 // if found, erase m_baskets[old_read_basket] to avoid
0524 // having all data in memory !
0525 std::map<uint32, std::pair<basket*,bool> >::iterator it = m_baskets.find(old_read_basket);
0526 if(it!=m_baskets.end()) {
0527 if((*it).second.second) {
0528 basket* bsk = (*it).second.first;
0529 m_baskets.erase(it);
0530 delete bsk;
0531 }
0532 }
0533 }
0534 }
0535
0536 if(!m__read_basket) {
0537
0538 basket* bsk = 0;
0539 std::map<uint32, std::pair<basket*,bool> >::iterator it = m_baskets.find(m_read_basket);
0540 if(it!=m_baskets.end()) {
0541 bsk = (*it).second.first;
0542 } else {
0543 if(m_read_basket>=m_write_basket) {
0544 m_out << "tools::rroot::branch::find_entry :"
0545 << " basket lacking !"
0546 << " wanting index " << m_read_basket
0547 << ". fBasketSeek entries " << m_write_basket
0548 << std::endl;
0549 return false;
0550 }
0551 if(!fBasketSeek[m_read_basket]) {
0552 m_out << "tools::rroot::branch::find_entry :"
0553 << " fBasketSeek is null for index " << m_read_basket
0554 << std::endl;
0555 return false;
0556 }
0557 if(!fBasketBytes[m_read_basket]) {
0558 m_out << "tools::rroot::branch::find_entry :"
0559 << " fBasketBytes is null for index " << m_read_basket
0560 << std::endl;
0561 return false;
0562 }
0563
0564 bsk = get_basket(a_file,fBasketSeek[m_read_basket],fBasketBytes[m_read_basket]);
0565 if(!bsk) {
0566 m_out << "tools::rroot::branch::find_entry :"
0567 << " can't read basket " << m_read_basket
0568 << " at file pos " << fBasketSeek[m_read_basket]
0569 << " and size " << fBasketBytes[m_read_basket]
0570 << std::endl;
0571 return false;
0572 }
0573 m_baskets[m_read_basket] = std::pair<basket*,bool>(bsk,true);
0574 }
0575
0576 m__read_basket = bsk;
0577 }
0578
0579 uint32 bufbegin;
0580 {int* entry_offset = m__read_basket->entry_offset();
0581 if(entry_offset) {
0582 uint32 index = uint32(a_entry-first);
0583 if(index>=m__read_basket->nev()) {
0584 m_out << "tools::rroot::branch::find_entry :"
0585 << " can't access entry offset " << index
0586 << ". nev " << m__read_basket->nev()
0587 << std::endl;
0588 return false;
0589 }
0590 bufbegin = entry_offset[index];
0591 } else {
0592 bufbegin = (uint32)(m__read_basket->key_length() + (a_entry-first)*m__read_basket->nev_buf_size());
0593 }}
0594
0595 {int* displacement = m__read_basket->displacement();
0596 if(displacement) {
0597 m_out << "tools::rroot::branch::find_entry :"
0598 << " not null displacement. Not yet handled."
0599 << std::endl;
0600 } else {
0601 }}
0602
0603
0604 buffer _buffer(m_out,a_file.byte_swap(),m__read_basket->buf_size(),m__read_basket->buf(),0,false);
0605 _buffer.set_offset(bufbegin);
0606 _buffer.set_map_objs(true); //for MEMPHYS/applications/read.icc
0607
0608 if(!read_leaves(a_file,_buffer)) {
0609 m_out << "tools::rroot::branch::find_entry :"
0610 << " can't read leaves for entry " << a_entry
0611 << ". read_basket was " << m_read_basket
0612 << ", first " << first
0613 << ", last " << last
0614 << "."
0615 << std::endl;
0616 return false;
0617 }
0618
0619 a_nbytes = _buffer.length() - bufbegin;
0620
0621 return true;
0622 }
0623
0624 virtual bool show(std::ostream& a_out,ifile& a_file,uint64 a_entry) {
0625 // Print values of all active leaves for entry :
0626 // if entry==-1, print current entry (default)
0627 uint32 n;
0628 if(!find_entry(a_file,a_entry,n)) return false;
0629
0630 tools_vforcit(base_leaf*,m_leaves,it) {
0631 base_leaf* bl = *it;
0632
0633 uint32 num = bl->num_elem();
0634 num = min_of<uint32>(num,10);
0635 if(!num) continue;
0636
0637 {std::string _s;
0638 uint32 len = uint32(bl->name().size())+128;
0639 sprintf(_s,len," %-15s = ",bl->name().c_str());
0640 a_out << _s;}
0641
0642 for(uint32 i=0;i<num;i++) {
0643 if(i) a_out << ", ";
0644 bl->print_value(a_out,i);
0645 }
0646
0647 a_out << std::endl;
0648 }
0649
0650 return true;
0651 }
0652 public:
0653 branch(std::ostream& a_out,ifac& a_fac)
0654 :m_out(a_out)
0655 ,m_fac(a_fac)
0656
0657 ,m_streamed_baskets(m_fac)
0658 ,m__read_basket(0)
0659
0660 //,m_bits(0)
0661 ,m_name("")
0662 ,m_title("")
0663 ,fAutoDelete(false)
0664
0665 ,m_branches(m_fac)
0666 ,m_leaves(m_fac)
0667
0668 ,fEntryOffsetLen(0)
0669 ,m_write_basket(0)
0670 ,m_entry_number(0)
0671 ,m_read_basket(0)
0672 ,fBasketBytes(0)
0673 ,fBasketEntry(0)
0674 ,fBasketSeek(0)
0675 {
0676 }
0677 virtual ~branch(){
0678 _clear();
0679 }
0680 protected:
0681 branch(const branch& a_from)
0682 :iro(a_from)
0683 ,m_out(a_from.m_out),m_fac(a_from.m_fac)
0684 ,m_streamed_baskets(m_fac)
0685 ,m__read_basket(0)
0686 ,fAutoDelete(false)
0687 ,m_branches(m_fac)
0688 ,m_leaves(m_fac)
0689 ,fEntryOffsetLen(1000)
0690 ,m_write_basket(0)
0691 ,m_entry_number(0)
0692 ,m_read_basket(0)
0693 ,fBasketBytes(0)
0694 ,fBasketEntry(0)
0695 ,fBasketSeek(0)
0696 {}
0697 branch& operator=(const branch&){return *this;}
0698 public:
0699 uint32 entry_number() const {return m_entry_number;}
0700 const std::string& name() const {return m_name;}
0701 const std::string& title() const {return m_title;}
0702 const std::vector<base_leaf*>& leaves() const {return m_leaves;}
0703 const std::vector<branch*>& branches() const {return m_branches;}
0704 protected:
0705 basket* get_basket(ifile& a_file,seek a_pos,uint32 a_len) {
0706 if(!a_len) return 0;
0707
0708 basket* _basket = new basket(m_out,a_pos,a_len); //basket is a key.
0709 if(!_basket->read_file(a_file)) {
0710 m_out << "tools::rroot::branch::get_basket :"
0711 << " read_file() failed."
0712 << std::endl;
0713 delete _basket;
0714 return 0;
0715 }
0716 {buffer _buffer(m_out,a_file.byte_swap(),a_len,_basket->buf(),0,false);
0717 if(!_basket->stream(_buffer)) {
0718 m_out << "tools::rroot::branch::get_basket :"
0719 << " basket stream failed."
0720 << std::endl;
0721 delete _basket;
0722 return 0;
0723 }}
0724 unsigned int sz;
0725 char* buf = _basket->get_object_buffer(a_file,sz); //basket owns buf.
0726 if(!buf) {
0727 m_out << "tools::rroot::branch::get_basket :"
0728 << " get_object_buffer() failed."
0729 << std::endl;
0730 delete _basket;
0731 return 0;
0732 }
0733
0734 if(_basket->seek_key()!=a_pos) { //consistency check.
0735 m_out << "tools::rroot::branch::get_basket :"
0736 << " seek anomaly."
0737 << " a_pos " << a_pos
0738 << " seek_key() " << _basket->seek_key()
0739 << std::endl;
0740 delete _basket;
0741 return 0;
0742 }
0743
0744 if(fEntryOffsetLen) {
0745 if(!_basket->read_offset_tables(a_file.byte_swap())) {
0746 m_out << "tools::rroot::branch::get_basket :"
0747 << " read_offset_tables failed."
0748 << std::endl;
0749 delete _basket;
0750 return 0;
0751 }}
0752
0753 return _basket;
0754 }
0755 protected:
0756 void _clear() {
0757 delete [] fBasketEntry;
0758 delete [] fBasketBytes;
0759 delete [] fBasketSeek;
0760 fBasketEntry = 0;
0761 fBasketBytes = 0;
0762 fBasketSeek = 0;
0763
0764 {for(auto it = m_baskets.begin(); it != m_baskets.end(); ++it) {
0765 if((*it).second.second) delete (*it).second.first;
0766 }
0767 m_baskets.clear();}
0768
0769 m_branches.cleanup();
0770 m_leaves.cleanup();
0771 m_streamed_baskets.cleanup();
0772 }
0773
0774 void _dump_first_last() {
0775 m_out << "tools::rroot::branch::_dump_first_last :"
0776 << " first_last " << m_first_last.size()
0777 << std::endl;
0778 for(auto it = m_first_last.cbegin(); it != m_first_last.cend(); ++it) {
0779 uint64 first = (*it).first;
0780 uint64 last = (*it).second;
0781 m_out << "tools::rroot::branch::stream :"
0782 << " first " << first
0783 << " last " << last
0784 << std::endl;
0785 }
0786 }
0787
0788 protected:
0789 std::ostream& m_out;
0790 ifac& m_fac;
0791 std::vector< std::pair<uint64,uint64> > m_first_last;
0792 std::map<uint32, std::pair<basket*,bool> > m_baskets;
0793 obj_array<basket> m_streamed_baskets;
0794 basket* m__read_basket; //optimization
0795 protected:
0796 std::string m_name;
0797 std::string m_title;
0798
0799 bool fAutoDelete;
0800 obj_array<branch> m_branches;
0801 obj_array<base_leaf> m_leaves;
0802 uint32 fEntryOffsetLen; // Initial Length of fEntryOffset table in the basket buffers
0803 uint32 m_write_basket; // Last basket number written
0804 uint32 m_entry_number; // Current entry number (last one filled in this branch)
0805 uint32 m_read_basket; //! Current basket number when reading
0806 int* fBasketBytes; //[fMaxBaskets] Length of baskets on file
0807 int* fBasketEntry; //[fMaxBaskets] Table of first entry in eack basket
0808 seek* fBasketSeek; //[fMaxBaskets] Addresses of baskets on file
0809 };
0810
0811 }}
0812
0813 #endif