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