Back to home page

EIC code displayed by LXR

 
 

    


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