TBranchElement.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TBranchElement.cxx 38394 2011-03-11 21:59:11Z pcanal $
00002 // Authors Rene Brun , Philippe Canal, Markus Frank  14/01/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TBranchElement                                                       //
00015 //                                                                      //
00016 // A Branch for the case of an object                                   //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 
00020 #include "TBranchElement.h"
00021 
00022 #include "TBasket.h"
00023 #include "TBranchObject.h"
00024 #include "TBranchRef.h"
00025 #include "TBrowser.h"
00026 #include "TClass.h"
00027 #include "TClassEdit.h"
00028 #include "TClonesArray.h"
00029 #include "TDataMember.h"
00030 #include "TDataType.h"
00031 #include "TError.h"
00032 #include "TMath.h"
00033 #include "TFile.h"
00034 #include "TFolder.h"
00035 #include "TLeafElement.h"
00036 #include "TRealData.h"
00037 #include "TStreamerElement.h"
00038 #include "TStreamerInfo.h"
00039 #include "TTree.h"
00040 #include "TVirtualCollectionProxy.h"
00041 #include "TVirtualCollectionIterators.h"
00042 #include "TVirtualPad.h"
00043 #include "TBranchSTL.h"
00044 #include "TVirtualArray.h"
00045 #include "TBufferFile.h"
00046 #include "TInterpreter.h"
00047 #include "TROOT.h"
00048 
00049 #include "TStreamerInfoActions.h"
00050 
00051 ClassImp(TBranchElement)
00052 
00053 //______________________________________________________________________________
00054 namespace {
00055    void RemovePrefix(TString& str, const char* prefix) {
00056       // -- Remove a prefix from a string.
00057       if (str.Length() && prefix && strlen(prefix)) {
00058          if (!str.Index(prefix)) {
00059             str.Remove(0, strlen(prefix));
00060          }
00061       }
00062    }
00063    struct R__PushCache {
00064       TBufferFile &fBuffer;
00065       TVirtualArray *fOnfileObject;
00066 
00067       R__PushCache(TBufferFile &b, TVirtualArray *in) : fBuffer(b), fOnfileObject(in) {
00068          if (fOnfileObject) fBuffer.PushDataCache( fOnfileObject );
00069       }
00070       ~R__PushCache() {
00071          if (fOnfileObject) fBuffer.PopDataCache();
00072       }
00073    };
00074 }
00075 
00076 //______________________________________________________________________________
00077 void TBranchElement::SwitchContainer(TObjArray* branches) {
00078    // -- Modify the container type of the branches
00079    
00080    const Int_t nbranches = branches->GetEntriesFast();
00081    for (Int_t i = 0; i < nbranches; ++i) {
00082       TBranchElement* br = (TBranchElement*) branches->At(i);
00083       switch (br->GetType()) {
00084          case 31: br->SetType(41); break;
00085          case 41: {
00086             br->SetType(31); 
00087             br->fCollProxy = 0;
00088             break;
00089          }
00090       }
00091       br->SetReadLeavesPtr();
00092       // Note: This is a tail recursion.
00093       SwitchContainer(br->GetListOfBranches());
00094    }
00095 }
00096 
00097 //______________________________________________________________________________
00098 namespace {
00099    Bool_t CanSelfReference(TClass *cl) {
00100       if (cl) {
00101          if (cl->GetCollectionProxy()) {
00102             TClass *inside = cl->GetCollectionProxy()->GetValueClass();
00103             if (inside) {
00104                return CanSelfReference(inside);
00105             } else {
00106                return kFALSE;
00107             }
00108          }
00109          static TClassRef stringClass("std::string");
00110          if (cl == stringClass || cl == TString::Class()) {
00111             return kFALSE;
00112          }
00113          // Here we could scan through the TStreamerInfo to see if there
00114          // is any pointer anywhere and know whether this is a possibility
00115          // of selfreference (but watch out for very indirect cases).
00116          return kTRUE;
00117       }
00118       return kFALSE;
00119    }
00120 }
00121 
00122 //______________________________________________________________________________
00123 TBranchElement::TBranchElement()
00124 : TBranch()
00125 , fClassName()
00126 , fParentName()
00127 , fClonesName()
00128 , fCollProxy(0)
00129 , fCheckSum(0)
00130 , fClassVersion(0)
00131 , fID(0)
00132 , fType(0)
00133 , fStreamerType(-1)
00134 , fMaximum(0)
00135 , fSTLtype(TClassEdit::kNotSTL)
00136 , fNdata(1)
00137 , fBranchCount(0)
00138 , fBranchCount2(0)
00139 , fInfo(0)
00140 , fObject(0)
00141 , fOnfileObject(0)
00142 , fInit(kFALSE)
00143 , fInitOffsets(kFALSE)
00144 , fTargetClass()
00145 , fCurrentClass()
00146 , fParentClass()
00147 , fBranchClass()
00148 , fBranchOffset(0)
00149 , fBranchID(-1)
00150 , fReadActionSequence(0)
00151 , fIterators(0)
00152 , fPtrIterators(0)
00153 {
00154    // -- Default and I/O constructor.
00155    fNleaves = 0;
00156    fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesImpl;
00157 }
00158 
00159 //______________________________________________________________________________
00160 TBranchElement::TBranchElement(TTree *tree, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
00161 : TBranch()
00162 , fClassName(sinfo->GetName())
00163 , fParentName()
00164 , fClonesName()
00165 , fCollProxy(0)
00166 , fCheckSum(sinfo->GetCheckSum())
00167 , fClassVersion(sinfo->GetClass()->GetClassVersion())
00168 , fID(id)
00169 , fType(0)
00170 , fStreamerType(-1)
00171 , fMaximum(0)
00172 , fSTLtype(TClassEdit::kNotSTL)
00173 , fNdata(1)
00174 , fBranchCount(0)
00175 , fBranchCount2(0)
00176 , fInfo(sinfo)
00177 , fObject(0)
00178 , fOnfileObject(0)
00179 , fInit(kTRUE)
00180 , fInitOffsets(kFALSE)
00181 , fTargetClass(fClassName)
00182 , fCurrentClass()
00183 , fParentClass()
00184 , fBranchClass(sinfo->GetClass())
00185 , fBranchOffset(0)
00186 , fBranchID(-1)
00187 , fReadActionSequence(0)
00188 , fIterators(0)
00189 , fPtrIterators(0)
00190 {
00191    // -- Constructor when the branch object is not a TClonesArray nor an STL container.
00192    //
00193    // If splitlevel > 0 this branch in turn is split into sub-branches.
00194 
00195    Init(tree, 0, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
00196 }
00197 
00198 //______________________________________________________________________________
00199 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
00200 : TBranch()
00201 , fClassName(sinfo->GetName())
00202 , fParentName()
00203 , fClonesName()
00204 , fCollProxy(0)
00205 , fCheckSum(sinfo->GetCheckSum())
00206 , fClassVersion(sinfo->GetClass()->GetClassVersion())
00207 , fID(id)
00208 , fType(0)
00209 , fStreamerType(-1)
00210 , fMaximum(0)
00211 , fSTLtype(TClassEdit::kNotSTL)
00212 , fNdata(1)
00213 , fBranchCount(0)
00214 , fBranchCount2(0)
00215 , fInfo(sinfo)
00216 , fObject(0)
00217 , fOnfileObject(0)
00218 , fInit(kTRUE)
00219 , fInitOffsets(kFALSE)
00220 , fTargetClass( fClassName )
00221 , fCurrentClass()
00222 , fParentClass()
00223 , fBranchClass(sinfo->GetClass())
00224 , fBranchOffset(0)
00225 , fBranchID(-1)
00226 , fReadActionSequence(0)
00227 , fIterators(0)
00228 , fPtrIterators(0)
00229 {
00230    // -- Constructor when the branch object is not a TClonesArray nor an STL container.
00231    //
00232    // If splitlevel > 0 this branch in turn is split into sub-branches.
00233 
00234    Init(parent ? parent->GetTree() : 0, parent, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
00235 }
00236 
00237 //______________________________________________________________________________
00238 void TBranchElement::Init(TTree *tree, TBranch *parent,const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
00239 {
00240    // -- Init when the branch object is not a TClonesArray nor an STL container.
00241    //
00242    // If splitlevel > 0 this branch in turn is split into sub-branches.
00243 
00244    TString name(bname);
00245 
00246    // Set our TNamed attributes.
00247    SetName(name);
00248    SetTitle(name);
00249 
00250    // Set our TBranch attributes.
00251    fSplitLevel = splitlevel;
00252    fTree   = tree;
00253    if (fTree == 0) return;
00254    fMother = parent ? parent->GetMother() : this;
00255    fParent = parent;
00256    fDirectory = fTree->GetDirectory();
00257    fFileName = "";
00258 
00259    // Clear the bit kAutoDelete to specify that when reading
00260    // the object should not be deleted before calling Streamer.
00261 
00262    SetAutoDelete(kFALSE);
00263 
00264    fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesImpl;
00265 
00266    //---------------------------------------------------------------------------
00267    // Handling the splitting of the STL collections of pointers
00268    //---------------------------------------------------------------------------
00269    Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
00270    splitlevel %= TTree::kSplitCollectionOfPointers;
00271 
00272    fCompress = -1;
00273    if (fTree->GetDirectory()) {
00274       TFile* bfile = fTree->GetDirectory()->GetFile();
00275       if (bfile) {
00276          fCompress = bfile->GetCompressionLevel();
00277       }
00278    }
00279 
00280    //
00281    // Initialize streamer type and element.
00282    //
00283 
00284    if (id > -1) {
00285       // We are *not* a top-level branch.
00286       ULong_t* elems = sinfo->GetElems();
00287       TStreamerElement* element = (TStreamerElement*) elems[id];
00288       fStreamerType = element->GetType();
00289    }
00290 
00291    //
00292    // Handle varying-length datatypes by allocating an offsets array.
00293    //
00294    // The fBits part of a TObject is of varying length because the pidf
00295    // is streamed only when the TObject is referenced by a TRef.
00296    //
00297 
00298    fEntryOffsetLen = 0;
00299    if (btype || (fStreamerType <= TVirtualStreamerInfo::kBase) || (fStreamerType == TVirtualStreamerInfo::kCharStar) || (fStreamerType == TVirtualStreamerInfo::kBits) || (fStreamerType > TVirtualStreamerInfo::kFloat16)) {
00300       fEntryOffsetLen = fTree->GetDefaultEntryOffsetLen();
00301    }
00302 
00303    //
00304    // Make sure the basket is big enough to contain the
00305    // entry offset array plus 100 bytes of data.
00306    //
00307 
00308    if (basketsize < (100 + fEntryOffsetLen)) {
00309       basketsize = 100 + fEntryOffsetLen;
00310    }
00311    fBasketSize = basketsize;
00312 
00313 
00314    //
00315    // Allocate and initialize the basket control arrays.
00316    //
00317 
00318    fBasketBytes = new Int_t[fMaxBaskets];
00319    fBasketEntry = new Long64_t[fMaxBaskets];
00320    fBasketSeek = new Long64_t[fMaxBaskets];
00321 
00322    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00323       fBasketBytes[i] = 0;
00324       fBasketEntry[i] = 0;
00325       fBasketSeek[i] = 0;
00326    }
00327 
00328    // We need to keep track of the counter branch if we have
00329    // one, since we cannot set it until we have created our
00330    // leaf, which we do last.
00331    TBranchElement* brOfCounter = 0;
00332 
00333    if (id < 0) {
00334       // -- We are a top-level branch.  Don't split a top-level branch, TTree::Bronch will do that work.
00335       if (fBranchClass.GetClass()) {
00336          Bool_t hasCustomStreamer = kFALSE;
00337          Bool_t canSelfReference = CanSelfReference(fBranchClass);
00338          if (fBranchClass.GetClass()->InheritsFrom(TObject::Class())) {
00339             if (canSelfReference) SetBit(kBranchObject);
00340             hasCustomStreamer = (!fBranchClass.GetClass()->GetCollectionProxy() && (gCint->ClassInfo_RootFlag(fBranchClass.GetClass()->GetClassInfo()) & 1));
00341          } else {
00342             if (canSelfReference) SetBit(kBranchAny);
00343             hasCustomStreamer = !fBranchClass.GetClass()->GetCollectionProxy() && (fBranchClass.GetClass()->GetStreamer() != 0 || (gCint->ClassInfo_RootFlag(fBranchClass.GetClass()->GetClassInfo()) & 1));
00344          }
00345          if (hasCustomStreamer) {
00346             fType = -1;
00347          }
00348       }
00349    } else {
00350       // -- We are a sub-branch of a split object.
00351       ULong_t* elems = sinfo->GetElems();
00352       TStreamerElement* element = (TStreamerElement*) elems[id];
00353       if ((fStreamerType == TVirtualStreamerInfo::kObject) || (fStreamerType == TVirtualStreamerInfo::kBase) || (fStreamerType == TVirtualStreamerInfo::kTNamed) || (fStreamerType == TVirtualStreamerInfo::kTObject) || (fStreamerType == TVirtualStreamerInfo::kObjectp) || (fStreamerType == TVirtualStreamerInfo::kObjectP)) {
00354          // -- If we are an object data member which inherits from TObject,
00355          // flag it so that later during i/o we will register the object
00356          // with the buffer so that pointers are handled correctly.
00357          if (CanSelfReference(fBranchClass)) {
00358             if (fBranchClass.GetClass()->InheritsFrom(TObject::Class())) {
00359                SetBit(kBranchObject);
00360             } else {
00361                SetBit(kBranchAny);
00362             }
00363          }
00364       }
00365       if (element->IsA() == TStreamerBasicPointer::Class()) {
00366          // -- Fixup title with counter if we are a varying length array data member.
00367          TStreamerBasicPointer *bp = (TStreamerBasicPointer *)element;
00368          TString countname;
00369          countname = bname;
00370          Ssiz_t dot = countname.Last('.');
00371          if (dot>=0) {
00372             countname.Remove(dot+1);
00373          } else {
00374             countname = "";
00375          }
00376          countname += bp->GetCountName();
00377          brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
00378          countname.Form("%s[%s]",name.Data(),bp->GetCountName());
00379          SetTitle(countname);
00380 
00381       } else if (element->IsA() == TStreamerLoop::Class()) {
00382          // -- Fixup title with counter if we are a varying length array data member.
00383          TStreamerLoop *bp = (TStreamerLoop *)element;
00384          TString countname;
00385          countname = bname;
00386          Ssiz_t dot = countname.Last('.');
00387          if (dot>=0) {
00388             countname.Remove(dot+1);
00389          } else {
00390             countname = "";
00391          }
00392          countname += bp->GetCountName();
00393          brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
00394          countname.Form("%s[%s]",name.Data(),bp->GetCountName());
00395          SetTitle(countname);
00396          
00397       }
00398       
00399       if (splitlevel > 0) {
00400          // -- Create sub branches if requested by splitlevel.
00401          const char* elem_type = element->GetTypeName();
00402          fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(elem_type));
00403          if (element->CannotSplit()) {
00404             fSplitLevel = 0;
00405          } else if (element->IsA() == TStreamerBase::Class()) {
00406             // -- We are a base class element.
00407             // Note: This does not include an STL container class which is
00408             //        being used as a base class because the streamer element
00409             //        in that case is not the base streamer element it is the
00410             //        STL streamer element.
00411             fType = 1;
00412             TClass* clOfElement = TClass::GetClass(element->GetName());
00413             Int_t nbranches = fBranches.GetEntriesFast();
00414             // Note: The following code results in base class branches
00415             //       having two different cases for what their parent
00416             //       class will be, this is very annoying.  It is also
00417             //       very annoying that the naming conventions for the
00418             //       sub-branch names are different as well.
00419             if (!strcmp(name, clOfElement->GetName())) {
00420                // -- If the branch's name is the same as the base class name,
00421                // which happens when we are a child branch of a top-level
00422                // branch whose name does not end in a dot and also has no
00423                // internal dots, elide the branch name, and keep the branch
00424                // heirarchy rooted at the ultimate parent, this keeps the base
00425                // class part of the branch name from propagating downwards.
00426                // FIXME: We are eliding the base class here, creating a break in the branch hierarchy.
00427                // Note: We can use parent class (cltop) != branch class (elemClass) to detection elision.
00428                Unroll("", fBranchClass.GetClass(), clOfElement, pointer, basketsize, splitlevel+splitSTLP, 0);
00429                SetReadLeavesPtr();
00430                return;
00431             }
00432             // If the branch's name is not the same as the base class name,
00433             // keep the branch name as a prefix (i.e., continue the branch
00434             // heirarchy), but start a new class heirarchy at the base class.
00435             //
00436             // Note: If the parent branch was created by the branch constructor
00437             //       which takes a folder as a parameter, then this case will
00438             //       be used, because the branch name will be the same as the
00439             //       parent branch name.
00440             // Note: This means that the sub-branches of a base class branch
00441             //       created by TTree::Bronch() have the base class name as
00442             //       as part of the branch name, while those created by
00443             //       Unroll() do not, ouch!!!
00444             //
00445             Unroll(name, clOfElement, clOfElement, pointer, basketsize, splitlevel+splitSTLP, 0);
00446             if (strchr(bname, '.')) {
00447                // Note: How can this happen?
00448                // Answer: This is the case when using the new branch
00449                //        naming convention where the top-level branch ends in dot.
00450                // Note: Well actually not entirely, we could also be a sub-branch
00451                //        of a split class, even when the top-level branch does not
00452                //        end in a dot.
00453                // Note: Or the top-level branch could have been created by the
00454                //        branch constructor which takes a folder as input, in which
00455                //        case the top-level branch name will have internal dots
00456                //        representing the folder hierarchy.
00457                SetReadLeavesPtr();
00458                return;
00459             }
00460             if (nbranches == fBranches.GetEntriesFast()) {
00461                // -- We did not add any branches in the Unroll, finalize our name to be the base class name, because Unroll did not do it for us.
00462                if (strlen(bname)) {
00463                   name.Form("%s.%s", bname, clOfElement->GetName());
00464                } else {
00465                   name.Form("%s", clOfElement->GetName());
00466                }
00467                SetName(name);
00468                SetTitle(name);
00469             }
00470             SetReadLeavesPtr();
00471             return;
00472          } else if (!strcmp(elem_type, "TClonesArray") || !strcmp(elem_type, "TClonesArray*")) {
00473             // -- We are a TClonesArray element.
00474             Bool_t ispointer = !strcmp(elem_type,"TClonesArray*");
00475             TClonesArray *clones;
00476             if (ispointer) {
00477                char **ppointer = (char**)(pointer);
00478                clones = (TClonesArray*)(*ppointer);
00479             } else {
00480                clones = (TClonesArray*)pointer;
00481             }
00482 //             basket->DeleteEntryOffset(); //entryoffset not required for the clonesarray counter
00483             fEntryOffsetLen = 0;
00484             // ===> Create a leafcount
00485             TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
00486             fNleaves = 1;
00487             fLeaves.Add(leaf);
00488             fTree->GetListOfLeaves()->Add(leaf);
00489             if (!clones) return;
00490             TClass* clOfClones = clones->GetClass();
00491             if (!clOfClones) {
00492                SetReadLeavesPtr();
00493                return;
00494             }
00495             fType = 3;
00496             // ===> create sub branches for each data member of a TClonesArray
00497             //check that the contained objects class name is part of the element title
00498             //This name is mandatory when reading the Tree later on and
00499             //the parent class with the pointer to the TClonesArray is not available.
00500             fClonesName = clOfClones->GetName();
00501             TString aname;
00502             aname.Form(" (%s)", clOfClones->GetName());
00503             TString atitle = element->GetTitle();
00504             if (!atitle.Contains(aname)) {
00505                atitle += aname;
00506                element->SetTitle(atitle.Data());
00507             }
00508             TString branchname( name );
00509             branchname += "_";
00510             SetTitle(branchname);
00511             leaf->SetName(branchname);
00512             leaf->SetTitle(branchname);
00513             Unroll(name, clOfClones, clOfClones, pointer, basketsize, splitlevel+splitSTLP, 31);
00514             BuildTitle(name);
00515             SetReadLeavesPtr();
00516             return;
00517          } else if (((fSTLtype >= TClassEdit::kVector) && (fSTLtype < TClassEdit::kEnd)) || ((fSTLtype > -TClassEdit::kEnd) && (fSTLtype <= -TClassEdit::kVector))) {
00518             // -- We are an STL container element.
00519             TClass* contCl = TClass::GetClass(elem_type);
00520             fCollProxy = contCl->GetCollectionProxy()->Generate();
00521             TClass* valueClass = GetCollectionProxy()->GetValueClass();
00522             // Check to see if we can split the container.
00523             Bool_t cansplit = kTRUE;
00524             if (!valueClass) {
00525                cansplit = kFALSE;
00526             } else if ((valueClass == TString::Class()) || (valueClass == TClass::GetClass("string"))) {
00527                cansplit = kFALSE;
00528             } else if (GetCollectionProxy()->HasPointers() && !splitSTLP ) {
00529                cansplit = kFALSE;
00530             } else if (!valueClass->CanSplit() && !(GetCollectionProxy()->HasPointers() && splitSTLP)) {
00531                cansplit = kFALSE;
00532             } else if (valueClass->GetCollectionProxy()) {
00533                // -- A collection was stored in a collection, we choose not to split it.
00534                // Note: Splitting it would require extending TTreeFormula
00535                //       to understand how to access it.
00536                cansplit = kFALSE;
00537             }
00538             if (cansplit) {
00539                // -- Do the splitting work if we are allowed to.
00540                fType = 4;
00541                // Create a leaf for the master branch (the counter).
00542                TLeaf *leaf = new TLeafElement(this, name, fID, fStreamerType);
00543                fNleaves = 1;
00544                fLeaves.Add(leaf);
00545                fTree->GetListOfLeaves()->Add(leaf);
00546                // Check that the contained objects class name is part of the element title.
00547                // This name is mandatory when reading the tree later on and
00548                // the parent class with the pointer to the STL container is not available.
00549                fClonesName = valueClass->GetName();
00550                TString aname;
00551                aname.Form(" (%s)", valueClass->GetName());
00552                TString atitle = element->GetTitle();
00553                if (!atitle.Contains(aname)) {
00554                   atitle += aname;
00555                   element->SetTitle(atitle.Data());
00556                }
00557                TString branchname (name);
00558                branchname += "_";
00559                SetTitle(branchname);
00560                leaf->SetName(branchname);
00561                leaf->SetTitle(branchname);
00562                // Create sub branches for each data member of an STL container.
00563                Unroll(name, valueClass, valueClass, pointer, basketsize, splitlevel+splitSTLP, 41);
00564                BuildTitle(name);
00565                SetReadLeavesPtr();
00566                return;
00567             }
00568          } else if (!strchr(elem_type, '*') && ((fStreamerType == TVirtualStreamerInfo::kObject) || (fStreamerType == TVirtualStreamerInfo::kAny))) {
00569             // -- Create sub-branches for members that are classes.
00570             //
00571             // Note: This can only happen if we were called directly
00572             //       (usually by TClass::Bronch) because Unroll never
00573             //       calls us for an element of this type.
00574             fType = 2;
00575             TClass* clm = TClass::GetClass(elem_type);
00576             Int_t err = Unroll(name, clm, clm, pointer, basketsize, splitlevel+splitSTLP, 0);
00577             if (err >= 0) {
00578                // Return on success.
00579                // FIXME: Why not on error too?
00580                SetReadLeavesPtr();
00581               return;
00582             }
00583          }
00584       }
00585    }
00586 
00587    //
00588    // Create a leaf to represent this branch.
00589    //
00590 
00591    TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
00592    leaf->SetTitle(GetTitle());
00593    fNleaves = 1;
00594    fLeaves.Add(leaf);
00595    fTree->GetListOfLeaves()->Add(leaf);
00596 
00597    //
00598    // If we have a counter branch set it now that we have
00599    // created our leaf, we cannot do it before then.
00600    //
00601 
00602    if (brOfCounter) {
00603       SetBranchCount(brOfCounter);
00604    }
00605 
00606    SetReadLeavesPtr();
00607 }
00608 
00609 //______________________________________________________________________________
00610 TBranchElement::TBranchElement(TTree *tree, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
00611 : TBranch()
00612 , fClassName("TClonesArray")
00613 , fParentName()
00614 , fInfo((TStreamerInfo*)TClonesArray::Class()->GetStreamerInfo())
00615 , fTargetClass( fClassName )
00616 , fCurrentClass()
00617 , fParentClass()
00618 , fBranchClass(TClonesArray::Class())
00619 , fBranchID(-1)
00620 , fReadActionSequence(0)
00621 , fIterators(0)
00622 , fPtrIterators(0)
00623 {
00624    // -- Constructor when the branch object is a TClonesArray.
00625    //
00626    // If splitlevel > 0 this branch in turn is split into sub branches.
00627 
00628    Init(tree, 0, bname, clones, basketsize, splitlevel, compress);
00629 }
00630 
00631 //______________________________________________________________________________
00632 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
00633 : TBranch()
00634 , fClassName("TClonesArray")
00635 , fParentName()
00636 , fInfo((TStreamerInfo*)TClonesArray::Class()->GetStreamerInfo())
00637 , fTargetClass( fClassName )
00638 , fCurrentClass()
00639 , fParentClass()
00640 , fBranchClass(TClonesArray::Class())
00641 , fBranchID(-1)
00642 , fReadActionSequence(0)
00643 , fIterators(0)
00644 , fPtrIterators(0)
00645 {
00646    // -- Constructor when the branch object is a TClonesArray.
00647    //
00648    // If splitlevel > 0 this branch in turn is split into sub branches.
00649 
00650    Init(parent ? parent->GetTree() : 0, parent, bname, clones, basketsize, splitlevel, compress);
00651 }
00652 
00653 //______________________________________________________________________________
00654 void TBranchElement::Init(TTree *tree, TBranch *parent, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
00655 {
00656    // -- Init when the branch object is a TClonesArray.
00657    //
00658    // If splitlevel > 0 this branch in turn is split into sub branches.
00659 
00660    fCollProxy = 0;
00661    fSplitLevel    = splitlevel;
00662    fID            = 0;
00663    fInit          = kTRUE;
00664    fStreamerType  = -1;
00665    fType          = 0;
00666    fClassVersion  = TClonesArray::Class()->GetClassVersion();
00667    fCheckSum      = fInfo->GetCheckSum();
00668    fBranchCount   = 0;
00669    fBranchCount2  = 0;
00670    fObject        = 0;
00671    fOnfileObject  = 0;
00672    fMaximum       = 0;
00673    fBranchOffset  = 0;
00674    fSTLtype       = TClassEdit::kNotSTL;
00675    fInitOffsets   = kFALSE;
00676 
00677    fTree          = tree;
00678    fMother        = parent ? parent->GetMother() : this;
00679    fParent        = parent;
00680    fDirectory     = fTree->GetDirectory();
00681    fFileName      = "";
00682 
00683    SetName(bname);
00684    const char* name = GetName();
00685    SetTitle(name);
00686    //fClassName = fInfo->GetName();
00687    fCompress = compress;
00688    if (compress == -1 && fTree->GetDirectory()) {
00689       TFile *bfile = fTree->GetDirectory()->GetFile();
00690       if (bfile) fCompress = bfile->GetCompressionLevel();
00691    }
00692 
00693    if (basketsize < 100) basketsize = 100;
00694    fBasketSize     = basketsize;
00695    fBasketBytes    = new Int_t[fMaxBaskets];
00696    fBasketEntry    = new Long64_t[fMaxBaskets];
00697    fBasketSeek     = new Long64_t[fMaxBaskets];
00698 
00699    for (Int_t i=0;i<fMaxBaskets;i++) {
00700       fBasketBytes[i] = 0;
00701       fBasketEntry[i] = 0;
00702       fBasketSeek[i]  = 0;
00703    }
00704 
00705    // Reset the bit kAutoDelete to specify that when reading
00706    // the object should not be deleted before calling the streamer.
00707    SetAutoDelete(kFALSE);
00708 
00709    // create sub branches if requested by splitlevel
00710    if (splitlevel%TTree::kSplitCollectionOfPointers > 0) {
00711       TClass* clonesClass = clones->GetClass();
00712       if (!clonesClass) {
00713          Error("Init","Missing class object of the TClonesArray %s\n",clones->GetName()); 
00714          return;
00715       }
00716       fType = 3;
00717       // ===> Create a leafcount
00718       TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
00719       fNleaves = 1;
00720       fLeaves.Add(leaf);
00721       fTree->GetListOfLeaves()->Add(leaf);
00722       // ===> create sub branches for each data member of a TClonesArray
00723       fClonesName = clonesClass->GetName();
00724       std::string branchname = name + std::string("_");
00725       SetTitle(branchname.c_str());
00726       leaf->SetName(branchname.c_str());
00727       leaf->SetTitle(branchname.c_str());
00728       Unroll(name, clonesClass, clonesClass, 0, basketsize, splitlevel, 31);
00729       BuildTitle(name);
00730       SetReadLeavesPtr();
00731       return;
00732    }
00733 
00734    if (!clones->GetClass() || CanSelfReference(clones->GetClass())) {
00735       SetBit(kBranchObject);
00736    }
00737    TLeaf *leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
00738    leaf->SetTitle(GetTitle());
00739    fNleaves = 1;
00740    fLeaves.Add(leaf);
00741    fTree->GetListOfLeaves()->Add(leaf);
00742    
00743    SetReadLeavesPtr();
00744 }
00745 
00746 //______________________________________________________________________________
00747 TBranchElement::TBranchElement(TTree *tree, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
00748 : TBranch()
00749 , fClassName(cont->GetCollectionClass()->GetName())
00750 , fParentName()
00751 , fTargetClass( fClassName )
00752 , fCurrentClass()
00753 , fParentClass()
00754 , fBranchClass(cont->GetCollectionClass())
00755 , fBranchID(-1)
00756 , fReadActionSequence(0)
00757 , fIterators(0)
00758 , fPtrIterators(0)
00759 {
00760    // -- Constructor when the branch object is an STL collection.
00761    //
00762    // If splitlevel > 0 this branch in turn is split into sub branches.
00763 
00764    Init(tree, 0, bname, cont, basketsize, splitlevel, compress);
00765 }
00766 
00767 //______________________________________________________________________________
00768 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
00769 : TBranch()
00770 , fClassName(cont->GetCollectionClass()->GetName())
00771 , fParentName()
00772 , fTargetClass( fClassName )
00773 , fCurrentClass()
00774 , fParentClass()
00775 , fBranchClass(cont->GetCollectionClass())
00776 , fBranchID(-1)
00777 , fReadActionSequence(0)
00778 , fIterators(0)
00779 , fPtrIterators(0)
00780 {
00781    // -- Constructor when the branch object is an STL collection.
00782    //
00783    // If splitlevel > 0 this branch in turn is split into sub branches.
00784 
00785    Init(parent ? parent->GetTree() : 0, parent, bname, cont, basketsize, splitlevel, compress);
00786 }
00787 
00788 //______________________________________________________________________________
00789 void TBranchElement::Init(TTree *tree, TBranch *parent, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
00790 {
00791    // -- Init when the branch object is an STL collection.
00792    //
00793    // If splitlevel > 0 this branch in turn is split into sub branches.
00794 
00795    fCollProxy = cont->Generate();
00796    TString name( bname );
00797    if (name[name.Length()-1]=='.') {
00798       name.Remove(name.Length()-1);
00799    }
00800    fInitOffsets   = kFALSE;
00801    fSplitLevel    = splitlevel;
00802    fInfo          = 0;
00803    fID            = -1;
00804    fInit          = kTRUE;
00805    fStreamerType  = -1; // TVirtualStreamerInfo::kSTLp;
00806    fType          = 0;
00807    fClassVersion  = cont->GetCollectionClass()->GetClassVersion();
00808    fCheckSum      = cont->GetCollectionClass()->GetCheckSum();
00809    fBranchCount   = 0;
00810    fBranchCount2  = 0;
00811    fObject        = 0;
00812    fOnfileObject  = 0;
00813    fMaximum       = 0;
00814    fBranchOffset  = 0;
00815    fSTLtype       = TClassEdit::kNotSTL;
00816 
00817    fTree          = tree;
00818    fMother        = parent ? parent->GetMother() : this;
00819    fParent        = parent;
00820    fDirectory     = fTree->GetDirectory();
00821    fFileName      = "";
00822 
00823    SetName(name);
00824    SetTitle(name);
00825    //fClassName = fBranchClass.GetClass()->GetName();
00826    fCompress = compress;
00827    if ((compress == -1) && fTree->GetDirectory()) {
00828       TFile* bfile = fTree->GetDirectory()->GetFile();
00829       if (bfile) {
00830          fCompress = bfile->GetCompressionLevel();
00831       }
00832    }
00833 
00834    if (basketsize < 100) {
00835       basketsize = 100;
00836    }
00837    fBasketSize     = basketsize;
00838 
00839    fBasketBytes    = new Int_t[fMaxBaskets];
00840    fBasketEntry    = new Long64_t[fMaxBaskets];
00841    fBasketSeek     = new Long64_t[fMaxBaskets];
00842 
00843    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00844       fBasketBytes[i] = 0;
00845       fBasketEntry[i] = 0;
00846       fBasketSeek[i] = 0;
00847    }
00848 
00849    // Reset the bit kAutoDelete to specify that, when reading,
00850    // the object should not be deleted before calling the streamer.
00851    SetAutoDelete(kFALSE);
00852 
00853    // create sub branches if requested by splitlevel
00854    if ( (splitlevel%TTree::kSplitCollectionOfPointers > 0 && fBranchClass.GetClass() && fBranchClass.GetClass()->CanSplit()) ||
00855         (cont->HasPointers() && splitlevel > TTree::kSplitCollectionOfPointers && cont->GetValueClass() && cont->GetValueClass()->CanSplit() ) )
00856    {
00857       fType = 4;
00858       // ===> Create a leafcount
00859       TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
00860       fNleaves = 1;
00861       fLeaves.Add(leaf);
00862       fTree->GetListOfLeaves()->Add(leaf);
00863       // ===> create sub branches for each data member of an STL container value class
00864       TClass* valueClass = cont->GetValueClass();
00865       if (!valueClass) {
00866          return;
00867       }
00868       fClonesName = valueClass->GetName();
00869       TString branchname( name );
00870       branchname += "_";
00871       SetTitle(branchname);
00872       leaf->SetName(branchname);
00873       leaf->SetTitle(branchname);
00874       Unroll(name, valueClass, valueClass, 0, basketsize, splitlevel, 41);
00875       BuildTitle(name);
00876       SetReadLeavesPtr();
00877       return;
00878    }
00879 
00880    TLeaf *leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
00881    leaf->SetTitle(GetTitle());
00882    fNleaves = 1;
00883    fLeaves.Add(leaf);
00884    fTree->GetListOfLeaves()->Add(leaf);
00885    SetReadLeavesPtr();
00886 }
00887 
00888 //______________________________________________________________________________
00889 TBranchElement::~TBranchElement()
00890 {
00891    // -- Destructor.
00892 
00893    // Release any allocated I/O buffers.
00894    if (fOnfileObject && TestBit(kOwnOnfileObj)) {
00895       delete fOnfileObject;
00896       fOnfileObject = 0;
00897    }
00898    ResetAddress();
00899 
00900    delete[] fBranchOffset;
00901    fBranchOffset = 0;
00902 
00903    fInfo = 0;
00904    fBranchCount2 = 0;
00905    fBranchCount = 0;
00906 
00907    if (fType == 4) {
00908       // Only the top level TBranchElement containing an STL container,
00909       // owns the collectionproxy.
00910       delete fCollProxy;
00911    }
00912    fCollProxy = 0;
00913    
00914    delete fReadActionSequence;
00915    delete fIterators;
00916    delete fPtrIterators;
00917 }
00918 
00919 //
00920 // This function is located here to allow inlining by the optimizer.
00921 //
00922 //______________________________________________________________________________
00923 inline TStreamerInfo* TBranchElement::GetInfoImp() const
00924 {
00925    // -- Get streamer info for the branch class.
00926    
00927    if (!fInfo || (fInfo && (!fInit || !fInfo->IsCompiled()))) {
00928       const_cast<TBranchElement*>(this)->InitInfo();
00929    }
00930    return fInfo;
00931 }
00932 
00933 //______________________________________________________________________________
00934 TStreamerInfo* TBranchElement::GetInfo() const
00935 {
00936    // -- Get streamer info for the branch class.
00937    
00938    return GetInfoImp();
00939 }
00940 
00941 //______________________________________________________________________________
00942 void TBranchElement::Browse(TBrowser* b)
00943 {
00944    // -- Browse the branch content.
00945 
00946    Int_t nbranches = fBranches.GetEntriesFast();
00947    if (nbranches > 0) {
00948       TList persistentBranches;
00949       TBranch* branch=0;
00950       TIter iB(&fBranches);
00951       while((branch=(TBranch*)iB())) {
00952          if (branch->IsFolder()) persistentBranches.Add(branch);
00953          else {
00954             // only show branches corresponding to persistent members
00955             TClass* cl=0;
00956             if (strlen(GetClonesName()))
00957                // this works both for top level branches and for sub-branches,
00958                // as GetClonesName() is properly updated for sub-branches
00959                cl=TClass::GetClass(GetClonesName());
00960             else {
00961                cl=TClass::GetClass(GetClassName());
00962 
00963                // check if we're in a sub-branch of this class
00964                // we can only find out asking the streamer given our ID
00965                ULong_t *elems=0;
00966                TStreamerElement *element=0;
00967                TClass* clsub=0;
00968                if (fID>=0 && GetInfoImp()
00969                    && ((elems=GetInfoImp()->GetElems()))
00970                    && ((element=(TStreamerElement *)elems[fID]))
00971                    && ((clsub=element->GetClassPointer())))
00972                   cl=clsub;
00973             }
00974             if (cl) {
00975                TString strMember=branch->GetName();
00976                Size_t mempos=strMember.Last('.');
00977                if (mempos!=kNPOS)
00978                   strMember.Remove(0, (Int_t)mempos+1);
00979                mempos=strMember.First('[');
00980                if (mempos!=kNPOS)
00981                   strMember.Remove((Int_t)mempos);
00982                TDataMember* m=cl->GetDataMember(strMember);
00983                if (!m || m->IsPersistent()) persistentBranches.Add(branch);
00984             } else persistentBranches.Add(branch);
00985          } // branch if not a folder
00986       }
00987       persistentBranches.Browse(b);
00988       // add all public const methods without params
00989       if (GetBrowsables() && GetBrowsables()->GetSize())
00990          GetBrowsables()->Browse(b);
00991    } else {
00992       if (GetBrowsables() && GetBrowsables()->GetSize()) {
00993          GetBrowsables()->Browse(b);
00994          return;
00995       }
00996       // Get the name and strip any extra brackets
00997       // in order to get the full arrays.
00998       TString slash("/");
00999       TString escapedSlash("\\/");
01000       TString name = GetName();
01001       Int_t pos = name.First('[');
01002       if (pos != kNPOS) {
01003          name.Remove(pos);
01004       }
01005       TString mothername;
01006       if (GetMother()) {
01007          mothername = GetMother()->GetName();
01008          pos = mothername.First('[');
01009          if (pos != kNPOS) {
01010             mothername.Remove(pos);
01011          }
01012          Int_t len = mothername.Length();
01013          if (len) {
01014             if (mothername(len-1) != '.') {
01015                // We do not know for sure whether the mother's name is
01016                // already preprended.  So we need to check:
01017                //    a) it is prepended
01018                //    b) it is NOT the name of a daugher (i.e. mothername.mothername exist)
01019                TString doublename = mothername;
01020                doublename.Append(".");
01021                Int_t isthere = (name.Index(doublename) == 0);
01022                if (!isthere) {
01023                   name.Prepend(doublename);
01024                } else {
01025                   if (GetMother()->FindBranch(mothername)) {
01026                      doublename.Append(mothername);
01027                      isthere = (name.Index(doublename) == 0);
01028                      if (!isthere) {
01029                         mothername.Append(".");
01030                         name.Prepend(mothername);
01031                      }
01032                   } else {
01033                      // Nothing to do because the mother's name is
01034                      // already in the name.
01035                   }
01036                }
01037             } else {
01038                // If the mother's name end with a dot then
01039                // the daughter probably already contains the mother's name
01040                if (name.Index(mothername) == kNPOS) {
01041                   name.Prepend(mothername);
01042                }
01043             }
01044          }
01045       }
01046       name.ReplaceAll(slash, escapedSlash);
01047       GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
01048       if (gPad) {
01049          gPad->Update();
01050       }
01051    }
01052 }
01053 
01054 //______________________________________________________________________________
01055 void TBranchElement::BuildTitle(const char* name)
01056 {
01057    // -- Set branch and leaf name and title in the case of a container sub-branch.
01058 
01059    TString branchname;
01060 
01061    Int_t nbranches = fBranches.GetEntries();
01062 
01063    for (Int_t i = 0; i < nbranches; ++i) {
01064       TBranchElement* bre = (TBranchElement*) fBranches.At(i);
01065       if (fType == 3) {
01066          bre->SetType(31);
01067       } else if (fType == 4) {
01068          bre->SetType(41);
01069       } else {
01070          Error("BuildTitle", "This cannot happen, fType of parent is not 3 or 4!");
01071       }
01072       bre->fCollProxy = GetCollectionProxy();
01073       bre->BuildTitle(name);
01074       const char* fin = strrchr(bre->GetTitle(), '.');
01075       if (fin == 0) {
01076          continue;
01077       }
01078       // The branch counter for a sub-branch of a container is the container master branch.
01079       bre->SetBranchCount(this);
01080       TLeafElement* lf = (TLeafElement*) bre->GetListOfLeaves()->At(0);
01081       // If branch name is of the form fTracks.fCovar[3][4], then
01082       // set the title to fCovar[fTracks_].
01083       branchname = fin+1;
01084       Ssiz_t dim = branchname.First('[');
01085       if (dim>=0) {
01086          branchname.Remove(dim);
01087       }
01088       branchname += Form("[%s_]",name);
01089       bre->SetTitle(branchname);
01090       if (lf) {
01091          lf->SetTitle(branchname);
01092       }
01093       // Is there a secondary branchcount?
01094       //
01095       // fBranchCount2 points to the secondary branchcount
01096       // in case a TClonesArray element itself has a branchcount.
01097       //
01098       // Example: In Event class with TClonesArray fTracks of Track objects.
01099       // if the Track object has two members
01100       //  Int_t    fNpoint;
01101       //  Float_t *fPoints;  //[fNpoint]
01102       // In this case the TBranchElement fTracks.fPoints has
01103       //  -its primary branchcount pointing to the branch fTracks
01104       //  -its secondary branchcount pointing to fTracks.fNpoint
01105       Int_t stype = bre->GetStreamerType();
01106       // FIXME: Should 60 be included here?
01107       if ((stype > 40) && (stype < 61)) {
01108          TString name2 (bre->GetName());
01109          Ssiz_t bn = name2.Last('.');
01110          if (bn<0) {
01111             continue;
01112          }
01113          TStreamerBasicPointer *el = (TStreamerBasicPointer*)bre->GetInfoImp()->GetElements()->FindObject(name2.Data()+bn+1);
01114          name2.Remove(bn+1);
01115          if (el) name2 += el->GetCountName();
01116          TBranchElement *bc2 = (TBranchElement*)fBranches.FindObject(name2);
01117          bre->SetBranchCount2(bc2);
01118       }
01119       bre->SetReadLeavesPtr();
01120    }
01121 }
01122 
01123 //______________________________________________________________________________
01124 Int_t TBranchElement::Fill()
01125 {
01126    // -- Loop on all leaves of this branch to fill the basket buffer.
01127    //
01128    // The function returns the number of bytes committed to the
01129    // individual branches.  If a write error occurs, the number of
01130    // bytes returned is -1.  If no data are written, because, e.g.,
01131    // the branch is disabled, the number of bytes returned is 0.
01132    //
01133    // Note: We not not use any member functions from TLeafElement!
01134 
01135    Int_t nbytes = 0;
01136    Int_t nwrite = 0;
01137    Int_t nerror = 0;
01138    Int_t nbranches = fBranches.GetEntriesFast();
01139 
01140    ValidateAddress();
01141 
01142    //
01143    // If we are a top-level branch, update addresses.
01144    //
01145 
01146    if (fID < 0) {
01147       if (!fObject) {
01148          Error("Fill", "attempt to fill branch %s while addresss is not set", GetName());
01149          return 0;
01150       }
01151    }
01152 
01153    //
01154    // If the tree has a TRefTable, set the current branch if
01155    // branch is not a basic type.
01156    //
01157 
01158    // FIXME: This test probably needs to be extended past 10.
01159    if ((fType >= -1) && (fType < 10)) {
01160       TBranchRef* bref = fTree->GetBranchRef();
01161       if (bref) {
01162          fBranchID = bref->SetParent(this, fBranchID);
01163       }
01164    }
01165 
01166    if (!nbranches) {
01167       // No sub-branches.
01168       if (!TestBit(kDoNotProcess)) {
01169          nwrite = TBranch::Fill();
01170          if (nwrite < 0) {
01171             Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
01172             ++nerror;
01173          } else {
01174             nbytes += nwrite;
01175          }
01176       }
01177    } else {
01178       // We have sub-branches.
01179       if (fType == 3 || fType == 4) {
01180          // TClonesArray or STL container counter
01181          nwrite = TBranch::Fill();
01182          if (nwrite < 0) {
01183             Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
01184             ++nerror;
01185          } else {
01186             nbytes += nwrite;
01187          }
01188       } else {
01189          ++fEntries;
01190       }
01191       for (Int_t i = 0; i < nbranches; ++i) {
01192          TBranchElement* branch = (TBranchElement*) fBranches[i];
01193          if (!branch->TestBit(kDoNotProcess)) {
01194             nwrite = branch->Fill();
01195             if (nwrite < 0) {
01196                Error("Fill", "Failed filling branch:%s.%s, nbytes=%d", GetName(), branch->GetName(), nwrite);
01197                nerror++;
01198             } else {
01199                nbytes += nwrite;
01200             }
01201          }
01202       }
01203    }
01204 
01205    if (fTree->Debug() > 0) {
01206       // Debugging.
01207       Long64_t entry = fEntries;
01208       if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
01209          printf("Fill: %lld, branch=%s, nbytes=%d\n", entry, GetName(), nbytes);
01210       }
01211    }
01212 
01213    if (nerror != 0) {
01214       return -1;
01215    }
01216 
01217    return nbytes;
01218 }
01219 
01220 //______________________________________________________________________________
01221 void TBranchElement::FillLeaves(TBuffer& b)
01222 {
01223    // -- Fill a buffer from the leaves of this branch.
01224    //
01225    // Note:  We do not use any member functions from TLeafElement!
01226    //        Except in the MakeClass case of a TClonesArray sub-branch.
01227 
01228    ValidateAddress();
01229 
01230    //
01231    // Silently do nothing if we have no user i/o buffer.
01232    //
01233 
01234    if (!fObject) {
01235       return;
01236    }
01237 
01238    //
01239    // Remember tobjects written to the buffer so that
01240    // pointers are handled correctly later.
01241 
01242    if (fType <=2) {
01243       if (TestBit(kBranchObject)) {
01244          b.MapObject((TObject*) fObject);
01245       } else if (TestBit(kBranchAny)) {
01246          b.MapObject(fObject, fBranchClass);
01247       }
01248    } else {
01249       // Case 3 and 4 nothing to do
01250       // Case 31 and 41, we should register the mother's fObject
01251    }
01252 
01253    //
01254    // Do the actual buffer filling now.
01255    //
01256 
01257    if (fType < 0) {
01258       // Non TObject, Non collection classes with a custom streamer.
01259       // if (fObject)
01260       fBranchClass->Streamer(fObject,b);
01261       return;
01262 
01263    } else if (fType <= 2) {
01264       // -- Top-level, data member, base class, or split class branch.
01265       // A non-split top-level branch (0, and fID == -1)), a non-split object (0, and fID > -1), or a base class (1), or a split (non-TClonesArray, non-STL container) object (2).  Write out the object.
01266       // Note: A split top-level branch (0, and fID == -2) should not happen here, see Fill().
01267       // FIXME: What happens with a split base class branch,
01268       //        or a split class branch???
01269       TStreamerInfo* si = GetInfoImp();
01270       if (!si) {
01271          Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
01272          return;
01273       }
01274       Int_t n = si->WriteBufferAux(b, &fObject, fID, 1, 0, 0);
01275       if ((fStreamerType == TVirtualStreamerInfo::kCounter) && (n > fMaximum)) {
01276          fMaximum = n;
01277       }
01278    } else if (fType == 3) {
01279       // -- TClonesArray top-level branch.  Write out number of entries, sub-branch writes the entries themselves.
01280       if (fTree->GetMakeClass()) {
01281          // Note: What if GetClonesName() is the zero pointer or an empty string?
01282          // Note: What if cl is a zero pointer here?
01283          // Answer: then fType would not have been set to 3, see TBranchElement::Init
01284          TClass* cl = TClass::GetClass(GetClonesName());
01285          TVirtualStreamerInfo* si = cl->GetStreamerInfo();
01286          if (!si) {
01287             Error("FillLeaves", "Cannot get streamer info for branch '%s' class '%s'", GetName(), cl->GetName());
01288             return;
01289          }
01290          b.ForceWriteInfo(si,kFALSE);
01291          Int_t* nptr = (Int_t*) fAddress;
01292          b << *nptr;
01293       } else {
01294          TClonesArray* clones = (TClonesArray*) fObject;
01295          Int_t n = clones->GetEntriesFast();
01296          if (n > fMaximum) {
01297             fMaximum = n;
01298          }
01299          b << n;
01300       }
01301    } else if (fType == 4) {
01302       // -- STL container top-level branch.  Write out number of entries, sub-branch writes the entries themselves.
01303       Int_t n = 0;
01304       {
01305          // We are in a block so the helper pops as soon as possible.
01306          TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(), fObject);
01307          n = GetCollectionProxy()->Size();
01308       }
01309       if (n > fMaximum) {
01310          fMaximum = n;
01311       }
01312       b << n;
01313    } else if (fType == 31) {
01314       // -- TClonesArray sub-branch.  Write out the entries in the TClonesArray.
01315       if (fTree->GetMakeClass()) {
01316          // -- A MakeClass() tree, we must use fAddress instead of fObject.
01317          if (!fAddress) {
01318             // FIXME: Enable this message.
01319             //Error("FillLeaves", "Branch address not set for branch '%s'!", GetName());
01320             return;
01321          }
01322          Int_t atype = fStreamerType;
01323          if (atype > 54) {
01324             // Note: We are not supporting kObjectp, kAny, kObjectp,
01325             //       kObjectP, kTString, kTObject, kTNamed, kAnyp,
01326             //       kAnyP, kSTLp, kSTL, kSTLstring, kStreamer,
01327             //       kStreamLoop here, nor pointers to varying length
01328             //       arrays of them either.
01329             //       Nor do we support pointers to varying length
01330             //       arrays of kBits, kLong64, kULong64, nor kBool.
01331             return;
01332          }
01333          Int_t* nn = (Int_t*) fBranchCount->GetAddress();
01334          if (!nn) {
01335             Error("FillLeaves", "The branch counter address was zero!");
01336             return;
01337          }
01338          Int_t n = *nn;
01339          if (atype > 40) {
01340             // Note: We are not supporting pointer to varying length array.
01341             Error("FillLeaves", "Clonesa: %s, n=%d, sorry not supported yet", GetName(), n);
01342             return;
01343          }
01344          if (atype > 20) {
01345             atype -= 20;
01346             TLeafElement* leaf = (TLeafElement*) fLeaves.UncheckedAt(0);
01347             n = n * leaf->GetLenStatic();
01348          }
01349          switch (atype) {
01350             // Note: Type 0 is a base class and cannot happen here, see Unroll().
01351             case TVirtualStreamerInfo::kChar     /*  1 */: { b.WriteFastArray((Char_t*)    fAddress, n); break; }
01352             case TVirtualStreamerInfo::kShort    /*  2 */: { b.WriteFastArray((Short_t*)   fAddress, n); break; }
01353             case TVirtualStreamerInfo::kInt      /*  3 */: { b.WriteFastArray((Int_t*)     fAddress, n); break; }
01354             case TVirtualStreamerInfo::kLong     /*  4 */: { b.WriteFastArray((Long_t*)    fAddress, n); break; }
01355             case TVirtualStreamerInfo::kFloat    /*  5 */: { b.WriteFastArray((Float_t*)   fAddress, n); break; }
01356             case TVirtualStreamerInfo::kCounter  /*  6 */: { b.WriteFastArray((Int_t*)     fAddress, n); break; }
01357             // FIXME: We do nothing with type 7 (TVirtualStreamerInfo::kCharStar, char*) here!
01358             case TVirtualStreamerInfo::kDouble   /*  8 */: { b.WriteFastArray((Double_t*)  fAddress, n); break; }
01359             case TVirtualStreamerInfo::kDouble32 /*  9 */: {
01360                TVirtualStreamerInfo* si = GetInfoImp();
01361                TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
01362                Double_t* xx = (Double_t*) fAddress;
01363                for (Int_t ii = 0; ii < n; ++ii) {
01364                   b.WriteDouble32(&(xx[ii]),se);
01365                }
01366                break;
01367             }
01368             case TVirtualStreamerInfo::kFloat16 /*  19 */: {
01369                TVirtualStreamerInfo* si = GetInfoImp();
01370                TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
01371                Float_t* xx = (Float_t*) fAddress;
01372                for (Int_t ii = 0; ii < n; ++ii) {
01373                   b.WriteFloat16(&(xx[ii]),se);
01374                }
01375                break;
01376             }
01377             // Note: Type 10 is unused for now.
01378             case TVirtualStreamerInfo::kUChar    /* 11 */: { b.WriteFastArray((UChar_t*)   fAddress, n); break; }
01379             case TVirtualStreamerInfo::kUShort   /* 12 */: { b.WriteFastArray((UShort_t*)  fAddress, n); break; }
01380             case TVirtualStreamerInfo::kUInt     /* 13 */: { b.WriteFastArray((UInt_t*)    fAddress, n); break; }
01381             case TVirtualStreamerInfo::kULong    /* 14 */: { b.WriteFastArray((ULong_t*)   fAddress, n); break; }
01382             // FIXME: This is wrong!!! TVirtualStreamerInfo::kBits is a variable length type.
01383             case TVirtualStreamerInfo::kBits     /* 15 */: { b.WriteFastArray((UInt_t*)    fAddress, n); break; }
01384             case TVirtualStreamerInfo::kLong64   /* 16 */: { b.WriteFastArray((Long64_t*)  fAddress, n); break; }
01385             case TVirtualStreamerInfo::kULong64  /* 17 */: { b.WriteFastArray((ULong64_t*) fAddress, n); break; }
01386             case TVirtualStreamerInfo::kBool     /* 18 */: { b.WriteFastArray((Bool_t*)    fAddress, n); break; }
01387          }
01388       } else {
01389          TClonesArray* clones = (TClonesArray*) fObject;
01390          Int_t n = clones->GetEntriesFast();
01391          TStreamerInfo* si = (TStreamerInfo*)GetInfoImp();
01392          if (!si) {
01393             Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
01394             return;
01395          }
01396          si->WriteBufferClones(b, clones, n, fID, fOffset);
01397       }
01398    } else if (fType == 41) {
01399       // -- STL container sub-branch.  Write out the entries in the STL container.
01400 
01401       // FIXME: This wont work if a pointer to vector is split!
01402       Int_t n = 0;
01403       TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(), fObject);
01404       n = GetCollectionProxy()->Size();
01405       // Note: We cannot pop the proxy here because we need it for the i/o.
01406       TStreamerInfo* si = (TStreamerInfo*)GetInfoImp();
01407       if (!si) {
01408          Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
01409          return;
01410       }
01411       if( fSplitLevel >= TTree::kSplitCollectionOfPointers )
01412          si->WriteBufferSTLPtrs(b, GetCollectionProxy(), n, fID, fOffset );
01413       else
01414          si->WriteBufferSTL(b, GetCollectionProxy(), n, fID, fOffset );
01415    }
01416 }
01417 
01418 //______________________________________________________________________________
01419 static void R__CleanName(std::string &name)
01420 {
01421    // Remove trailing dimensions and make sure
01422    // there is a trailing dot.
01423 
01424    if (name[name.length()-1]==']') {
01425       std::size_t dim = name.find_first_of("[");
01426       if (dim != std::string::npos) {
01427          name.erase(dim);
01428       }
01429    }
01430    if (name[name.size()-1] != '.') {
01431       name += '.';
01432    }
01433 }
01434 
01435 //______________________________________________________________________________
01436 TBranch* TBranchElement::FindBranch(const char *name)
01437 {
01438    // Find the immediate sub-branch with passed name.
01439 
01440    // The default behavior of TBranch::FindBranch is sometimes
01441    // incorrect if this branch represent a base class, since
01442    // the base class name might or might not be in the name
01443    // of the sub-branches and might or might not be in the
01444    // name being passed.
01445 
01446    if (fID >= 0) {
01447       TVirtualStreamerInfo* si = GetInfoImp();
01448       TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
01449       if (se && se->IsBase()) {
01450          // We allow the user to pass only the last dotted component of the name.
01451          UInt_t len = strlen(name);
01452          std::string longnm;
01453          longnm.reserve(fName.Length()+len+3); // Enough space of fName + name + dots
01454          longnm = fName.Data();
01455          R__CleanName(longnm);
01456          longnm += name;
01457          std::string longnm_parent;
01458          longnm_parent.reserve(fName.Length()+len+3);
01459          longnm_parent = (GetMother()->GetSubBranch(this)->GetName());
01460          R__CleanName(longnm_parent);
01461          longnm_parent += name;  // Name without the base class name
01462 
01463          UInt_t namelen = strlen(name);
01464 
01465          TBranch* branch = 0;
01466          Int_t nbranches = fBranches.GetEntries();
01467          for(Int_t i = 0; i < nbranches; ++i) {
01468             branch = (TBranch*) fBranches.UncheckedAt(i);
01469 
01470             const char *brname = branch->GetName();
01471             UInt_t brlen = strlen(brname);
01472             if (brname[brlen-1]==']') {
01473                const char *dim = strchr(brname,'[');
01474                if (dim) {
01475                   brlen = dim - brname;
01476                }
01477             }
01478             if (namelen == brlen /* same effective size */
01479                 && strncmp(name,brname,brlen) == 0) {
01480                return branch;
01481             }
01482             if (brlen == longnm.length()
01483                 && strncmp(longnm.c_str(),brname,brlen) == 0) {
01484                 return branch;
01485             }
01486             // This check is specific to base class
01487             if (brlen == longnm_parent.length()
01488                 && strncmp(longnm_parent.c_str(),brname,brlen) == 0) {
01489                return branch;
01490             }
01491 
01492             if (namelen>brlen && name[brlen]=='.' && strncmp(name,brname,brlen)==0) {
01493                // The prefix subbranch name match the branch name.
01494                return branch->FindBranch(name+brlen+1);
01495             }
01496          }
01497       }
01498    }
01499    TBranch *result = TBranch::FindBranch(name);
01500    if (!result) {
01501       // Look in base classes if any
01502       Int_t nbranches = fBranches.GetEntries();
01503       for(Int_t i = 0; i < nbranches; ++i) {
01504          TObject *obj = fBranches.UncheckedAt(i);
01505          if(obj->IsA() != TBranchElement :: Class() )
01506             continue;
01507          TBranchElement *br = (TBranchElement*)obj;
01508          TVirtualStreamerInfo* si = br->GetInfoImp();
01509          if (si && br->GetID() >= 0) {
01510             TStreamerElement* se = (TStreamerElement*) si->GetElems()[br->GetID()];
01511             if (se && se->IsBase()) {
01512                result = br->FindBranch(name);
01513             }
01514          }
01515       }
01516    }
01517    return result;
01518 }
01519 
01520 //______________________________________________________________________________
01521 TLeaf* TBranchElement::FindLeaf(const char *name)
01522 {
01523    // -- Find the leaf corresponding to the name 'searchname'.
01524 
01525    TLeaf *leaf = TBranch::FindLeaf(name);
01526 
01527    if (leaf==0 && GetListOfLeaves()->GetEntries()==1) {
01528       TBranch *br = GetMother()->GetSubBranch( this );
01529       if( br->IsA() != TBranchElement::Class() )
01530          return 0;
01531 
01532       TBranchElement *parent = (TBranchElement*)br;
01533       if (parent==this || parent->GetID()<0 ) return 0;
01534 
01535       TVirtualStreamerInfo* si = parent->GetInfoImp();
01536       TStreamerElement* se = (TStreamerElement*) si->GetElems()[parent->GetID()];
01537 
01538       if (! se->IsBase() ) return 0;
01539 
01540       br = GetMother()->GetSubBranch( parent );
01541       if( br->IsA() != TBranchElement::Class() )
01542          return 0;
01543 
01544       TBranchElement *grand_parent = (TBranchElement*)br;
01545 
01546       std::string longname( grand_parent->GetName() );
01547       R__CleanName(longname);
01548       longname += name;
01549 
01550       std::string leafname( GetListOfLeaves()->At(0)->GetName() );
01551 
01552       if ( longname == leafname ) {
01553          return (TLeaf*)GetListOfLeaves()->At(0);
01554       }
01555    }
01556    return leaf;
01557 }
01558 
01559 //______________________________________________________________________________
01560 char* TBranchElement::GetAddress() const
01561 {
01562    // -- Get the branch address.
01563    //
01564    // If we are *not* owned by a MakeClass() tree:
01565    //
01566    //      If we are a top-level branch, return a pointer
01567    //      to the pointer to our object.
01568    //
01569    //      If we are *not* a top-level branch, return a pointer
01570    //      to our object.
01571    //
01572    // If we are owned by a MakeClass() tree:
01573    //
01574    //      Return a pointer to our object.
01575    //
01576 
01577    ValidateAddress();
01578    return fAddress;
01579 }
01580 
01581 //______________________________________________________________________________
01582 void TBranchElement::InitInfo()
01583 {
01584    // -- Init the streamer info for the branch class, try to compensate for class code unload/reload and schema evolution.
01585 
01586    if (!fInfo) {
01587       // We did not already have streamer info, so now we must find it.
01588       TClass* cl = fBranchClass.GetClass();
01589 
01590       //------------------------------------------------------------------------
01591       // Check if we're dealing with the name change
01592       //------------------------------------------------------------------------
01593       TClass* targetClass = 0;
01594       if( fTargetClass.GetClassName()[0]) {
01595          targetClass = fTargetClass;
01596          if( !targetClass ) {
01597             Error( "InitInfo", "The target class dictionary is not present!" );
01598             return;
01599          }
01600       } else {
01601          targetClass = cl;
01602       }
01603 
01604       if (cl) {
01605          //---------------------------------------------------------------------
01606          // Get the streamer info for given version
01607          //---------------------------------------------------------------------
01608          {
01609             if( targetClass != cl ) {
01610                fInfo = (TStreamerInfo*)targetClass->GetConversionStreamerInfo( cl, fClassVersion );
01611             } else {
01612                fInfo = (TStreamerInfo*)cl->GetStreamerInfo(fClassVersion);
01613             }
01614          }
01615 
01616          // FIXME: Check that the found streamer info checksum matches our branch class checksum here.
01617          // Check to see if the class code was unloaded/reloaded
01618          // since we were created.
01619          if (fCheckSum && (cl->IsForeign() || (!cl->IsLoaded() && (fClassVersion == 1) && cl->GetStreamerInfos()->At(1) && (fCheckSum != ((TVirtualStreamerInfo*) cl->GetStreamerInfos()->At(1))->GetCheckSum())))) {
01620             // Try to compensate for a class that got unloaded on us.
01621             // Search through the streamer infos by checksum
01622             // and take the first match.
01623 
01624             TStreamerInfo* info;
01625             if( targetClass != cl )
01626                info = (TStreamerInfo*)targetClass->GetConversionStreamerInfo( cl, fCheckSum );
01627             else {
01628                info = (TStreamerInfo*)cl->FindStreamerInfo( fCheckSum );
01629                if (info) {
01630                   // Now that we found it, we need to make sure it is initialize (Find does not initialize the StreamerInfo).
01631                   info = (TStreamerInfo*)cl->GetStreamerInfo(info->GetClassVersion());
01632                }
01633             }
01634             if( info ) {
01635                fInfo = info;
01636                // We no longer reset the class version so that in case the user is passing us later
01637                // the address of a class that require (another) Conversion we can find the proper
01638                // StreamerInfo.
01639                //    fClassVersion = fInfo->GetClassVersion();
01640             }
01641          }
01642       }
01643    }
01644 
01645    //
01646    //  Fixup cached streamer info if necessary.
01647    //
01648    // FIXME:  What if the class code was unloaded/reloaded since we were cached?
01649 
01650    if (fInfo) {
01651 
01652       if ( GetID()>-1 && (!fInfo->IsCompiled() || fInfo->IsOptimized()) ) {
01653          // Streamer info has not yet been compiled.
01654          //
01655          // Optimizing does not work with splitting.
01656          fInfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
01657          fInfo->Compile();
01658       }
01659       if (!fInit) {
01660          // We were read in from a file, figure out what our fID should be,
01661          // schema evolution must be considered.
01662          //
01663          // Force our fID to be the id of the first streamer element that matches our name.
01664          //
01665          if (GetID() > -1) {
01666             // We are *not* a top-level branch.
01667             std::string s(GetName());
01668             size_t pos = s.rfind('.');
01669             if (pos != std::string::npos) {
01670                s = s.substr(pos+1);
01671             }
01672             while ((pos = s.rfind('[')) != std::string::npos) {
01673                s = s.substr(0, pos);
01674             }
01675             int offset = 0;
01676             TStreamerElement* elt = fInfo->GetStreamerElement(s.c_str(), offset);
01677             if (elt && offset!=TStreamerInfo::kMissing) {
01678                size_t ndata = fInfo->GetNdata();
01679                ULong_t* elems = fInfo->GetElems();
01680                fIDs.clear();
01681                for (size_t i = 0; i < ndata; ++i) {
01682                   if (((TStreamerElement*) elems[i]) == elt) {
01683                      if (elt->TestBit (TStreamerElement::kCache)
01684                          && elt->TestBit(TStreamerElement::kRepeat)
01685                          && (i+1) < ndata
01686                          && s == ((TStreamerElement*) elems[i])->GetName())
01687                      {
01688                         // If the TStreamerElement we found is storing the information in the
01689                         // cache and is a repeater, we need to use the real one (the next one).
01690                         // (At least until the cache/repeat mechanism is properly handle by
01691                         // ReadLeaves).
01692                         // fID = i+1;
01693                         fID = i;
01694                         fIDs.push_back(fID+1);
01695                      } else {
01696                         fID = i;
01697                      }
01698                      if (elt->TestBit (TStreamerElement::kCache)) {
01699                         SetBit(TBranchElement::kCache);
01700                      }
01701                      break;
01702                   }
01703                }
01704                for (size_t i = fID+1+(fIDs.size()); i < ndata; ++i) {
01705                   TStreamerElement *nextel = ((TStreamerElement*) elems[i]);
01706                   // Add all (and only) the Artificial Elements that follows this StreamerInfo.
01707                   if (fType==31||fType==41) {
01708                      // The nested objects are unfolded and their branch can not be used to
01709                      // execute StreamerElements of this StreamerInfo.
01710                      if (nextel->GetType() == TStreamerInfo::kObject
01711                          || nextel->GetType() == TStreamerInfo::kAny) {
01712                         continue;
01713                      }
01714                   }
01715                   if (nextel->GetOffset() ==  TStreamerInfo::kMissing) {
01716                      // This element will be 'skipped', it's TBranchElement's fObject will null
01717                      // and thus can not be used to execute the artifical StreamerElements
01718                      continue;
01719                   }
01720                   if (nextel->IsA() != TStreamerArtificial::Class()
01721                       || nextel->GetType() == TStreamerInfo::kCacheDelete ) {
01722                      break;
01723                   }
01724                   fIDs.push_back(i);
01725                }
01726             } else if (elt && offset==TStreamerInfo::kMissing) {
01727                // Still re-assign fID properly.
01728                fIDs.clear();
01729                size_t ndata = fInfo->GetNdata();
01730                ULong_t* elems = fInfo->GetElems();
01731                for (size_t i = 0; i < ndata; ++i) {
01732                   if (((TStreamerElement*) elems[i]) == elt) {
01733                      fID = i;
01734                      break;
01735                   }
01736                }
01737             } else {
01738                // We have not even found the element .. this is strange :(
01739                // fIDs.clear();
01740                // fID = -3;
01741                // SetBit(kDoNotProcess);
01742             }
01743             if (fOnfileObject==0 && (fType==31 || fType==41 || (0 <= fType && fType <=2) ) && fInfo->GetNdata()
01744                 && ((TStreamerElement*) fInfo->GetElems()[0])->GetType() == TStreamerInfo::kCacheNew)
01745             {
01746                Int_t arrlen = 1;
01747                if (fType==31 || fType==41) {
01748                   TLeaf *leaf = (TLeaf*)fLeaves.At(0);
01749                   if (leaf) {
01750                      arrlen = leaf->GetMaximum();
01751                   }
01752                }
01753                fOnfileObject = new TVirtualArray( ((TStreamerElement*) fInfo->GetElems()[0])->GetClassPointer(), arrlen );
01754                // Propage this to all the other branch of this type.
01755                TObjArray *branches = GetMother()->GetSubBranch(this)->GetListOfBranches();
01756                Int_t nbranches = branches->GetEntriesFast();
01757                TBranchElement *lastbranch = this;
01758                for (Int_t i = 0; i < nbranches; ++i) {
01759                   TBranchElement* subbranch = (TBranchElement*)branches->At(i);
01760                   if (this!=subbranch && subbranch->fBranchClass == fBranchClass && subbranch->fCheckSum == fCheckSum) {
01761                      subbranch->fOnfileObject = fOnfileObject;
01762                      lastbranch = subbranch;
01763                   }
01764                }
01765                lastbranch->SetBit(kOwnOnfileObj);
01766             }
01767          }
01768          fInit = kTRUE;
01769 
01770          // Get the action sequence we need to copy for reading.
01771          SetReadActionSequence();
01772       } else if (!fReadActionSequence) {
01773          // Get the action sequence we need to copy for reading.
01774          SetReadActionSequence();
01775       }
01776       SetReadLeavesPtr();
01777    }
01778 }
01779 
01780 //______________________________________________________________________________
01781 TVirtualCollectionProxy* TBranchElement::GetCollectionProxy()
01782 {
01783    // -- Return the collection proxy describing the branch content, if any.
01784 
01785    if (fCollProxy) {
01786       return fCollProxy;
01787    }
01788    TBranchElement* thiscast = const_cast<TBranchElement*>(this);
01789    if (fType == 4) {
01790       // STL container top-level branch.
01791       const char* className = 0;
01792       if (fID < 0) {
01793          // We are a top-level branch.
01794          if (fBranchClass.GetClass()) {
01795            className = fBranchClass.GetClass()->GetName();
01796          }
01797       } else {
01798          // We are not a top-level branch.
01799          TVirtualStreamerInfo* si = thiscast->GetInfoImp();
01800          TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
01801          className = se->GetTypeName();
01802       }
01803       TClass* cl = TClass::GetClass(className);
01804       TVirtualCollectionProxy* proxy = cl->GetCollectionProxy();
01805       fCollProxy = proxy->Generate();
01806       fSTLtype = className ? TClassEdit::IsSTLCont(className) : 0;
01807       if (fSTLtype < 0) {
01808         fSTLtype = -fSTLtype;
01809       }
01810    } else if (fType == 41) {
01811       // STL container sub-branch.
01812       thiscast->fCollProxy = fBranchCount->GetCollectionProxy();
01813    }
01814    return fCollProxy;
01815 }
01816 
01817 //______________________________________________________________________________
01818 TClass* TBranchElement::GetCurrentClass()
01819 {
01820    // -- Return a pointer to the current type of the data member corresponding to branch element.
01821 
01822    TClass* cl = fCurrentClass;
01823    if (cl) {
01824       return cl;
01825    }
01826 
01827    TStreamerInfo* brInfo = (TStreamerInfo*)GetInfoImp();
01828    if (!brInfo) {
01829       cl = TClass::GetClass(GetClassName());
01830       R__ASSERT(cl && cl->GetCollectionProxy());
01831       fCurrentClass = cl;
01832       return cl;
01833    }
01834    TClass* motherCl = brInfo->GetClass();
01835    if (motherCl->GetCollectionProxy()) {
01836       cl = motherCl->GetCollectionProxy()->GetCollectionClass();
01837       if (cl) {
01838          fCurrentClass = cl;
01839       }
01840       return cl;
01841    }
01842    if (GetID() < 0 || GetID()>=brInfo->GetNdata()) {
01843       return 0;
01844    }
01845    TStreamerElement* currentStreamerElement = ((TStreamerElement*) brInfo->GetElems()[GetID()]);
01846    TDataMember* dm = (TDataMember*) motherCl->GetListOfDataMembers()->FindObject(currentStreamerElement->GetName());
01847 
01848    TString newType;
01849    if (!dm) {
01850       // Either the class is not loaded or the data member is gone
01851       if (!motherCl->IsLoaded()) {
01852          TVirtualStreamerInfo* newInfo = motherCl->GetStreamerInfo();
01853          if (newInfo != brInfo) {
01854             TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(currentStreamerElement->GetName());
01855             if (newElems) {
01856                newType = newElems->GetClassPointer()->GetName();
01857             }
01858          }
01859          if (newType.Length()==0) {
01860             newType = currentStreamerElement->GetClassPointer()->GetName();
01861          }
01862       }
01863    } else {
01864       newType = dm->GetTypeName();
01865    }
01866    cl = TClass::GetClass(newType);
01867    if (cl) {
01868       fCurrentClass = cl;
01869    }
01870    return cl;
01871 }
01872 
01873 //______________________________________________________________________________
01874 Int_t TBranchElement::GetEntry(Long64_t entry, Int_t getall)
01875 {
01876    // -- Read all branches of a BranchElement and return total number of bytes.
01877    //
01878    // If entry = 0, then use current entry number + 1.
01879    // If entry < 0, then reset entry number to 0.
01880    //
01881    // Returns the number of bytes read from the input buffer.
01882    // If entry does not exist, then returns 0.
01883    // If an I/O error occurs, then returns -1.
01884    //
01885    // See IMPORTANT REMARKS in TTree::GetEntry.
01886    //
01887 
01888    // Remember which entry we are reading.
01889    fReadEntry = entry;
01890 
01891    // If our tree has a branch ref, make it remember the entry and
01892    // this branch.  This allows a TRef::GetObject() call done during
01893    // the following I/O operation, for example in a custom streamer,
01894    // to search for the referenced object in the proper element of the
01895    // proper branch.
01896    TBranchRef* bref = fTree->GetBranchRef();
01897    if (bref) {
01898       fBranchID = bref->SetParent(this, fBranchID);
01899       bref->SetReadEntry(entry);
01900    }
01901 
01902    Int_t nbytes = 0;
01903 
01904    if (IsAutoDelete()) {
01905       SetBit(kDeleteObject);
01906       SetAddress(fAddress);
01907    }
01908    SetupAddresses();
01909 
01910    Int_t nbranches = fBranches.GetEntriesFast();
01911    if (nbranches) {
01912       // -- Branch has daughters.
01913       // One must always read the branch counter.
01914       // In the case when one reads consecutively twice the same entry,
01915       // the user may have cleared the TClonesArray between the GetEntry calls.
01916       if ((fType == 3) || (fType == 4)) {
01917          Int_t nb = TBranch::GetEntry(entry, getall);
01918          if (nb < 0) {
01919             return nb;
01920          }
01921          nbytes += nb;
01922       }
01923       switch(fSTLtype) {
01924          case TClassEdit::kSet:
01925          case TClassEdit::kMultiSet:
01926          case TClassEdit::kMap:
01927          case TClassEdit::kMultiMap:
01928             break;
01929          default:
01930             for (Int_t i = 0; i < nbranches; ++i) {
01931                TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
01932                Int_t nb = branch->GetEntry(entry, getall);
01933                if (nb < 0) {
01934                   return nb;
01935                }
01936                nbytes += nb;
01937             }
01938             break;
01939       }
01940    } else {
01941       // -- Terminal branch.
01942       if (fBranchCount && (fBranchCount->GetReadEntry() != entry)) {
01943          Int_t nb = fBranchCount->TBranch::GetEntry(entry, getall);
01944          if (nb < 0) {
01945             return nb;
01946          }
01947          nbytes += nb;
01948       }
01949       Int_t nb = TBranch::GetEntry(entry, getall);
01950       if (nb < 0) {
01951          return nb;
01952       }
01953       nbytes += nb;
01954    }
01955 
01956    if (fTree->Debug() > 0) {
01957       if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
01958          Info("GetEntry", "%lld, branch=%s, nbytes=%d", entry, GetName(), nbytes);
01959       }
01960    }
01961    return nbytes;
01962 }
01963 
01964 //______________________________________________________________________________
01965 Int_t TBranchElement::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
01966 {
01967    // Fill expectedClass and expectedType with information on the data type of the 
01968    // object/values contained in this branch (and thus the type of pointers
01969    // expected to be passed to Set[Branch]Address
01970    // return 0 in case of success and > 0 in case of failure.
01971    
01972    expectedClass = 0;
01973    expectedType = kOther_t;
01974    
01975    Int_t type = GetStreamerType();
01976    if ((type == -1) || (fID == -1)) {
01977       expectedClass = fBranchClass;
01978    } else {
01979       // Case of an object data member.  Here we allow for the
01980       // variable name to be ommitted.  Eg, for Event.root with split
01981       // level 1 or above  Draw("GetXaxis") is the same as Draw("fH.GetXaxis()")
01982       TStreamerElement* element = (TStreamerElement*) GetInfoImp()->GetElems()[fID];
01983       if (element) {
01984          expectedClass = element->GetClassPointer();
01985          if (!expectedClass) {
01986             TDataType* data = gROOT->GetType(element->GetTypeNameBasic());
01987             if (!data) {
01988                Error("GetExpectedType", "Did not find the type number for %s", element->GetTypeNameBasic());
01989                return 1;
01990             } else {
01991                expectedType = (EDataType) data->GetType();
01992             }
01993          }
01994       } else {
01995          Error("GetExpectedType", "Did not find the type for %s",GetName());
01996          return 2;
01997       }
01998    }
01999    return 0;
02000 }
02001 
02002 //______________________________________________________________________________
02003 const char* TBranchElement::GetIconName() const
02004 {
02005    // -- Return icon name depending on type of branch element.
02006 
02007    if (IsFolder()) {
02008       return "TBranchElement-folder";
02009    } else {
02010       return "TBranchElement-leaf";
02011    }
02012 }
02013 
02014 //______________________________________________________________________________
02015 Bool_t TBranchElement::GetMakeClass() const
02016 {
02017    // Return whether this branch is in a mode where the object are decomposed
02018    // or not (Also known as MakeClass mode).
02019    
02020    return TestBit(kDecomposedObj); // Same as TestBit(kMakeClass)
02021 }
02022 
02023 //______________________________________________________________________________
02024 Int_t TBranchElement::GetMaximum() const
02025 {
02026    // -- Return maximum count value of the branchcount if any.
02027 
02028    if (fBranchCount) {
02029       return fBranchCount->GetMaximum();
02030    }
02031    return fMaximum;
02032 }
02033 
02034 //______________________________________________________________________________
02035 char* TBranchElement::GetObject() const
02036 {
02037    // -- Return a pointer to our object.
02038 
02039    ValidateAddress();
02040    return fObject;
02041 }
02042 
02043 //______________________________________________________________________________
02044 TClass* TBranchElement::GetParentClass()
02045 {
02046    // -- Return a pointer to the parent class of the branch element.
02047    return fParentClass.GetClass();
02048 }
02049 
02050 //______________________________________________________________________________
02051 const char* TBranchElement::GetTypeName() const
02052 {
02053    // -- Return type name of element in the branch.
02054 
02055    if (fType == 3  || fType == 4) {
02056       return "Int_t";
02057    }
02058    // FIXME: Use symbolic constants here.
02059    if ((fStreamerType < 1) || (fStreamerType > 59)) {
02060       if (fBranchClass.GetClass()) {
02061          if (fID>=0) {
02062             ULong_t* elems = GetInfoImp()->GetElems();
02063             return ((TStreamerElement*) elems[fID])->GetTypeName();
02064          } else {
02065             return fBranchClass.GetClass()->GetName();
02066          }
02067       } else {
02068          return 0;
02069       }
02070    }
02071    const char *types[20] = {
02072       "",
02073       "Char_t",
02074       "Short_t",
02075       "Int_t",
02076       "Long_t",
02077       "Float_t",
02078       "Int_t",
02079       "char*",
02080       "Double_t",
02081       "Double32_t",
02082       "",
02083       "UChar_t",
02084       "UShort_t",
02085       "UInt_t",
02086       "ULong_t",
02087       "UInt_t",
02088       "Long64_t",
02089       "ULong64_t",
02090       "Bool_t",
02091       "Float16_t"
02092    };
02093    Int_t itype = fStreamerType % 20;
02094    return types[itype];
02095 }
02096 
02097 //______________________________________________________________________________
02098 Double_t TBranchElement::GetValue(Int_t j, Int_t len, Bool_t subarr) const
02099 {
02100    // -- Returns the branch value.
02101    //
02102    // If the leaf is an array, j is the index in the array.
02103    //
02104    // If leaf is an array inside a TClonesArray, len should be the length
02105    // of the array.
02106    //
02107    // If subarr is true, then len is actually the index within the sub-array.
02108    //
02109 
02110    ValidateAddress();
02111 
02112    Int_t prID = fID;
02113    char *object = fObject;
02114    if (TestBit(kCache)) {
02115       if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
02116          prID = fID+1;
02117       } else if (fOnfileObject) {
02118          object = fOnfileObject->GetObjectAt(0);
02119       }
02120    }
02121 
02122    if (!j && fBranchCount) {
02123       Int_t entry = fTree->GetReadEntry();
02124       // Since reloading the index, will reset the ClonesArray, let's
02125       // skip the load if we already read this entry.
02126       if (entry != fBranchCount->GetReadEntry()) {
02127          fBranchCount->TBranch::GetEntry(entry);
02128       }
02129       if (fBranchCount2 && entry != fBranchCount2->GetReadEntry()) {
02130          fBranchCount2->TBranch::GetEntry(entry);
02131       }
02132    }
02133 
02134    if (fTree->GetMakeClass()) {
02135       if (!fAddress) {
02136          return 0;
02137       }
02138       if ((fType == 3) || (fType == 4)) {
02139          // Top-level branch of a TClonesArray.
02140          return (Double_t) fNdata;
02141       } else if ((fType == 31) || (fType == 41)) {
02142          // sub branch of a TClonesArray
02143          Int_t atype = fStreamerType;
02144          if (atype < 20) {
02145             atype += 20;
02146          }
02147          return GetInfoImp()->GetValue(fAddress, atype, j, 1);
02148       } else if (fType <= 2) {
02149          // branch in split mode
02150          // FIXME: This should probably be < 60 instead!
02151          if ((fStreamerType > 40) && (fStreamerType < 55)) {
02152             Int_t atype = fStreamerType - 20;
02153             return GetInfoImp()->GetValue(fAddress, atype, j, 1);
02154          } else {
02155             return GetInfoImp()->GetValue(object, prID, j, -1);
02156          }
02157       }
02158    }
02159 
02160    if (fType == 31) {
02161       TClonesArray* clones = (TClonesArray*) object;
02162       if (subarr) {
02163          return GetInfoImp()->GetValueClones(clones, prID, j, len, fOffset);
02164       }
02165       return GetInfoImp()->GetValueClones(clones, prID, j/len, j%len, fOffset);
02166    } else if (fType == 41) {
02167       TVirtualCollectionProxy::TPushPop helper(((TBranchElement*) this)->GetCollectionProxy(), object);
02168       if( fSplitLevel < TTree::kSplitCollectionOfPointers )
02169       {
02170          if (subarr)
02171             return GetInfoImp()->GetValueSTL(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
02172 
02173          return GetInfoImp()->GetValueSTL(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
02174       }
02175       else
02176       {
02177          if (subarr)
02178             return GetInfoImp()->GetValueSTLP(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
02179          return GetInfoImp()->GetValueSTLP(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
02180       }
02181    } else {
02182       if (GetInfoImp()) {
02183          return GetInfoImp()->GetValue(object, prID, j, -1);
02184       }
02185       return 0;
02186    }
02187 }
02188 
02189 //______________________________________________________________________________
02190 void* TBranchElement::GetValuePointer() const
02191 {
02192    // -- Returns pointer to first data element of this branch.
02193    // Currently used only for members of type character.
02194 
02195    ValidateAddress();
02196 
02197    Int_t prID = fID;
02198    char *object = fObject;
02199    if (TestBit(kCache)) {
02200       if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
02201          prID = fID+1;
02202       } else if (fOnfileObject) {
02203          object = fOnfileObject->GetObjectAt(0);
02204       }
02205    }
02206 
02207    if (fBranchCount) {
02208       Int_t entry = fTree->GetReadEntry();
02209       fBranchCount->TBranch::GetEntry(entry);
02210       if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
02211    }
02212    if (fTree->GetMakeClass()) {
02213       if (!fAddress) {
02214          return 0;
02215       }
02216       if (fType == 3) {    //top level branch of a TClonesArray
02217          //return &fNdata;
02218          return 0;
02219       } else if (fType == 4) {    //top level branch of a TClonesArray
02220          //return &fNdata;
02221          return 0;
02222       } else if (fType == 31) {    // sub branch of a TClonesArray
02223          //Int_t atype = fStreamerType;
02224          //if (atype < 20) atype += 20;
02225          //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
02226          return 0;
02227       } else if (fType == 41) {    // sub branch of a TClonesArray
02228          //Int_t atype = fStreamerType;
02229          //if (atype < 20) atype += 20;
02230          //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
02231          return 0;
02232       } else if (fType <= 2) {     // branch in split mode
02233          // FIXME: This should probably be < 60 instead!
02234          if (fStreamerType > 40 && fStreamerType < 55) {
02235             //Int_t atype = fStreamerType - 20;
02236             //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
02237             return 0;
02238          } else {
02239             //return GetInfoImp()->GetValue(object, fID, j, -1);
02240             return 0;
02241          }
02242       }
02243    }
02244 
02245    if (fType == 31) {
02246       return 0;
02247    } else if (fType == 41) {
02248       return 0;
02249    } else {
02250       //return GetInfoImp()->GetValue(object,fID,j,-1);
02251       if (!GetInfoImp() || !object) return 0;
02252       char **val = (char**)(object+GetInfoImp()->GetOffsets()[fID]);
02253       return *val;
02254    }
02255 }
02256 
02257 //______________________________________________________________________________
02258 void TBranchElement::InitializeOffsets()
02259 {
02260    // -- Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a container sub-branch.
02261    //
02262    // Note: The offsets are zero for data members so that when
02263    //       SetAddress recursively sets their address, they will get the
02264    //       same address as their containing class because i/o is based
02265    //       on streamer info offsets from the addresss of the containing
02266    //       class.
02267    //
02268    //       Offsets are non-zero for base-class sub-branches that are
02269    //       not the leftmost direct base class.  They are laid out in
02270    //       memory sequentially and only the leftmost direct base class
02271    //       has the same address as the derived class.  The streamer
02272    //       offsets need to be added to the address of the base class
02273    //       subobject which is not the same as the address of the
02274    //       derived class for the non-leftmost direct base classes.
02275 
02276    Int_t nbranches = fBranches.GetEntriesFast();
02277 
02278    if (fID < 0) {
02279       // -- We are a top-level branch.  Let's mark whether we need to use MapObject.
02280       if (CanSelfReference(fBranchClass)) {
02281          if (fBranchClass.GetClass()->InheritsFrom(TObject::Class())) {
02282             SetBit(kBranchObject);
02283          } else {
02284             SetBit(kBranchAny);
02285          }
02286       }
02287    }
02288    if (nbranches) {
02289       // Allocate space for the new sub-branch offsets.
02290       delete[] fBranchOffset;
02291       fBranchOffset = 0;
02292       fBranchOffset = new Int_t[nbranches];
02293       // Make sure we can instantiate our class meta info.
02294       if (!fBranchClass.GetClass()) {
02295          Warning("InitializeOffsets", "No branch class set for branch: %s", GetName());
02296          fInitOffsets = kTRUE;
02297          return;
02298       }
02299       // Make sure we can instantiate our class streamer info.
02300       if (!GetInfoImp()) {
02301          Warning("InitializeOffsets", "No streamer info available for branch: %s of class: %s", GetName(), fBranchClass.GetClass()->GetName());
02302          fInitOffsets = kTRUE;
02303          return;
02304       }
02305 
02306       // Get the class we are a member of now (which is the
02307       // type of our containing subobject) and get our offset
02308       // inside of our containing subobject (our local offset).
02309       // Note: branchElem stays zero if we are a top-level branch,
02310       //       we have to be careful about this later.
02311       TStreamerElement* branchElem = 0;
02312       Int_t localOffset = 0;
02313       TClass* branchClass = fBranchClass.GetClass();
02314       if (fID > -1) {
02315          // -- Branch is *not* a top-level branch.
02316          // Instead of the streamer info class, we want the class of our
02317          // specific element in the streamer info.  We could be a data
02318          // member of a base class or a split class, in which case our
02319          // streamer info will be for our containing sub-object, while
02320          // we are actually a different type.
02321          TVirtualStreamerInfo* si = GetInfoImp();
02322          // Note: We tested to make sure the streamer info was available previously.
02323          ULong_t* elems = si->GetElems();
02324          if (!elems) {
02325             Warning("InitializeOffsets", "Streamer info for branch: %s has no elements array!", GetName());
02326             fInitOffsets = kTRUE;
02327             return;
02328          }
02329          // FIXME: Check that fID is in range.
02330          branchElem = (TStreamerElement*) elems[fID];
02331          if (!branchElem) {
02332             Warning("InitializeOffsets", "Cannot get streamer element for branch: %s!", GetName());
02333             fInitOffsets = kTRUE;
02334             return;
02335          }
02336          localOffset = branchElem->GetOffset();
02337          branchClass = branchElem->GetClassPointer();
02338          if (localOffset == TStreamerInfo::kMissing) {
02339             fObject = 0;
02340          }
02341       }
02342       if (!branchClass) {
02343          Error("InitializeOffsets", "Could not find class for branch: %s", GetName());
02344          fInitOffsets = kTRUE;
02345          return;
02346       }
02347 
02348       //------------------------------------------------------------------------
02349       // Extract the name of the STL branch in case we're splitting the
02350       // collection of pointers
02351       //------------------------------------------------------------------------
02352       TString stlParentName;
02353       Bool_t stlParentNameUpdated = kFALSE;
02354       if( fType == 4 && fSplitLevel > TTree::kSplitCollectionOfPointers )
02355       {
02356          TBranch *br = GetMother()->GetSubBranch( this );
02357          stlParentName = br->GetName();
02358          stlParentName.Strip( TString::kTrailing, '.' );
02359 
02360          // We may ourself contain the 'Mother' branch name.
02361          // To avoid code duplication, we delegate the removal
02362          // of the mother's name to the first sub-branch loop.
02363       }
02364 
02365       // Loop over our sub-branches and compute their offsets.
02366       for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
02367          fBranchOffset[subBranchIdx] = 0;
02368          TBranchElement* subBranch = dynamic_cast<TBranchElement*> (fBranches[subBranchIdx]);
02369          if (subBranch == 0) {
02370             // -- Skip sub-branches that are not TBranchElements.
02371             continue;
02372          }
02373             
02374          TVirtualStreamerInfo* sinfo = subBranch->GetInfoImp();
02375          if (!sinfo) {
02376             Warning("InitializeOffsets", "No streamer info for branch: %s subbranch: %s", GetName(), subBranch->GetName());
02377             fInitOffsets = kTRUE;
02378             return;
02379          }
02380          ULong_t* subBranchElems = sinfo->GetElems();
02381          if (!subBranchElems) {
02382             Warning("InitializeOffsets", "No elements array for branch: %s subbranch: %s", GetName(), subBranch->GetName());
02383             fInitOffsets = kTRUE;
02384             return;
02385          }
02386          // FIXME: Make sure subBranch->fID is in range.
02387          TStreamerElement* subBranchElement = (TStreamerElement*) subBranchElems[subBranch->fID];
02388          if (!subBranchElement) {
02389             Warning("InitializeOffsets", "No streamer element for branch: %s subbranch: %s", GetName(), subBranch->GetName());
02390             fInitOffsets = kTRUE;
02391             return;
02392          }
02393 
02394          localOffset = subBranchElement->GetOffset();
02395          if (localOffset == TStreamerInfo::kMissing) {
02396             subBranch->fObject = 0;
02397          }
02398 
02399          {
02400             Int_t streamerType = subBranchElement->GetType();
02401             if (streamerType > TStreamerInfo::kObject
02402                 && subBranch->GetListOfBranches()->GetEntries()==0
02403                 && CanSelfReference(subBranchElement->GetClass()))
02404             {
02405                subBranch->SetBit(kBranchAny);
02406             } else {
02407                subBranch->ResetBit(kBranchAny);
02408             }
02409          }
02410 
02411          if (subBranchElement->GetNewType()<0) {
02412             subBranch->ResetBit(kBranchAny);
02413             subBranch->ResetBit(kBranchObject);
02414          }
02415 
02416          // Note: This call is expensive, do it only once.
02417          TBranch* mother = GetMother();
02418          if (!mother) {
02419             Warning("InitializeOffsets", "Branch '%s' has no mother!", GetName());
02420             fInitOffsets = kTRUE;
02421             return;
02422          }
02423          TString motherName(mother->GetName());
02424          Bool_t motherDot = kFALSE;
02425          if (motherName.Length() && strchr(motherName.Data(), '.')) {
02426             motherDot = kTRUE;
02427          }
02428          Bool_t motherDotAtEnd = kFALSE;
02429          if (motherName.Length() && (motherName[motherName.Length()-1] == '.')) {
02430             motherDotAtEnd = kTRUE;
02431          }
02432 
02433          Bool_t isBaseSubBranch = kFALSE;
02434          if ((subBranch->fType == 1) || (subBranchElement && subBranchElement->IsBase())) {
02435             // -- Base class sub-branch (1).
02436             //
02437             // Note: Our type will not be 1, even though we are
02438             // a base class branch, if we are not split (see the
02439             // constructor), or if we are an STL container master
02440             // branch and a base class branch at the same time
02441             // or an std::string.
02442             isBaseSubBranch = kTRUE;
02443          }
02444 
02445          Bool_t isContDataMember = kFALSE;
02446          if ((subBranch->fType == 31) || (subBranch->fType == 41)) {
02447             // -- Container data member sub-branch (31 or 41).
02448             isContDataMember = kTRUE;
02449          }
02450 
02451          // I am either a data member sub-branch (0), or a base class
02452          // sub-branch (1), or TClonesArray master sub-branch (3),
02453          // or an STL container master sub-branch (4), or TClonesArray
02454          // data member sub-branch (31), or an STL container data member
02455          // sub-branch (41).
02456          //
02457          // My parent branch is either a top-level branch ((0), fID==(-2,-1)),
02458          // or a base class sub-branch (1), or a split-class branch (2),
02459          // or a TClonesArray master branch (3), or an STL container
02460          // master branch (4).
02461          //
02462 
02463          //
02464          // We need to extract from our name the name
02465          // of the data member which contains us, so
02466          // that we may then do a by-name lookup in the
02467          // dictionary meta info of our parent class to
02468          // get our offset in our parent class.
02469          //
02470 
02471          // Get our name.
02472          TString dataName(subBranch->GetName());
02473          if (motherDotAtEnd) {
02474             // -- Remove the top-level branch name from our name.
02475             dataName.Remove(0, motherName.Length());
02476             // stlParentNameUpdated is false the first time in this loop.
02477             if (!stlParentNameUpdated && stlParentName.Length()) {
02478                stlParentName.Remove(0, motherName.Length());
02479                stlParentNameUpdated = kTRUE;
02480             }
02481          } else if (motherDot) {
02482             // -- Remove the top-level branch name from our name, folder case.
02483             //
02484             // Note: We are in the case where our mother was created
02485             //       by the branch constructor which takes a folder
02486             //       as an argument.  The mother branch has internal
02487             //       dots in its name to represent the folder heirarchy.
02488             //       The TTree::Bronch() routine has handled us as a
02489             //       special case, we must compensate.
02490             if ((fID < 0) && (subBranchElement->IsA() == TStreamerBase::Class())) {
02491                // -- Our name is the mother name, remove it.
02492                // Note: The test is our parent is a top-level branch
02493                //       and our streamer is the base class streamer,
02494                //       this matches the exact test in TTree::Bronch().
02495                if (dataName.Length() == motherName.Length()) {
02496                   dataName.Remove(0, motherName.Length());
02497                   // stlParentNameUpdated is false the first time in this loop.
02498                   if (!stlParentNameUpdated && stlParentName.Length()) {
02499                      stlParentName.Remove(0, motherName.Length());
02500                   }
02501                }
02502             } else {
02503                // -- Remove the mother name and the dot.
02504                if (dataName.Length() > motherName.Length()) {
02505                   dataName.Remove(0, motherName.Length() + 1);
02506                   if (!stlParentNameUpdated && stlParentName.Length()) {
02507                      stlParentName.Remove(0, motherName.Length());
02508                   }
02509                }
02510             }
02511          }
02512          stlParentNameUpdated = kTRUE;
02513          if (isBaseSubBranch) {
02514             // -- Remove the base class name suffix from our name.
02515             // Note: The pattern is the name of the base class.
02516             TString pattern(subBranchElement->GetName());
02517             if (pattern.Length() <= dataName.Length()) {
02518                if (!strcmp(dataName.Data() + (dataName.Length() - pattern.Length()), pattern.Data())) {
02519                   // The branch name contains the name of the base class in it.
02520                   // This name is not reproduced in the sub-branches, so we need to
02521                   // remove it.
02522                   dataName.Remove(dataName.Length() - pattern.Length());
02523                }
02524             }
02525             // Remove any leading dot.
02526             if (dataName.Length()) {
02527                if (dataName[0] == '.') {
02528                   dataName.Remove(0, 1);
02529                }
02530             }
02531             // Note: We intentionally leave any trailing dot
02532             //       in our modified name here.
02533          }
02534 
02535          // Get our parent branch's name.
02536          TString parentName(GetName());
02537          if (motherDotAtEnd) {
02538             // -- Remove the top-level branch name from our parent's name.
02539             parentName.Remove(0, motherName.Length());
02540          } else if (motherDot) {
02541             // -- Remove the top-level branch name from our parent's name, folder case.
02542             //
02543             // Note: We are in the case where our mother was created
02544             //       by the branch constructor which takes a folder
02545             //       as an argument.  The mother branch has internal
02546             //       dots in its name to represent the folder heirarchy.
02547             //       The TTree::Bronch() routine has handled us as a
02548             //       special case, we must compensate.
02549             if ((fID > -1) && (mother == mother->GetSubBranch(this)) && (branchElem->IsA() == TStreamerBase::Class())) {
02550                // -- Our parent's name is the mother name, remove it.
02551                // Note: The test is our parent's parent is a top-level branch
02552                //       and our parent's streamer is the base class streamer,
02553                //       this matches the exact test in TTree::Bronch().
02554                if (parentName.Length() == motherName.Length()) {
02555                   parentName.Remove(0, motherName.Length());
02556                }
02557             } else {
02558                // -- Remove the mother name and the dot.
02559                if (parentName.Length() > motherName.Length()) {
02560                   parentName.Remove(0, motherName.Length() + 1);
02561                }
02562             }
02563          }
02564          // FIXME: Do we need to use the other tests for a base class here?
02565          if (fType == 1) {
02566             // -- Our parent is a base class sub-branch, remove the base class name suffix from its name.
02567             if (mother != mother->GetSubBranch(this)) {
02568                // -- My parent's parent is not a top-level branch.
02569                // Remove the base class name suffix from the parent name.
02570                // Note: The pattern is the name of the base class.
02571                TString pattern(branchElem->GetName());
02572                if (pattern.Length() <= parentName.Length()) {
02573                   if (!strcmp(parentName.Data() + (parentName.Length() - pattern.Length()), pattern.Data())) {
02574                      // The branch name contains the name of the base class in it.
02575                      // This name is not reproduced in the sub-branches, so we need to
02576                      // remove it.
02577                      parentName.Remove(parentName.Length() - pattern.Length());
02578                   }
02579                }
02580             }
02581             // Note: We intentionally leave any trailing dots
02582             //       in the modified parent name here.
02583          }
02584 
02585          // Remove the parent branch name part from our name,
02586          // but only if the parent branch is not a top-level branch.
02587          // FIXME: We should not assume parent name does not have length 0.
02588          if (fID > -1) {
02589            RemovePrefix(dataName, parentName);
02590          }
02591 
02592          // Remove any leading dot.
02593          if (dataName.Length()) {
02594             if (dataName[0] == '.') {
02595                dataName.Remove(0, 1);
02596             }
02597          }
02598 
02599          // Remove any trailing dot.
02600          if (dataName.Length()) {
02601             if (dataName[dataName.Length()-1] == '.') {
02602                dataName.Remove(dataName.Length() - 1, 1);
02603             }
02604          }
02605 
02606          //
02607          // Now that we have our data member name, find our offset
02608          // in our parent class.
02609          //
02610          // Note:  Our data member name can have many dots in it
02611          //        if branches were elided between our parent branch
02612          //        and us by Unroll().
02613          //
02614          // FIXME: This may not work if our member name is ambiguous.
02615          //
02616 
02617          Int_t offset = 0;
02618          if (dataName.Length()) {
02619             // -- We have our data member name, do a lookup in the dictionary meta info of our parent class.
02620             // Get our parent class.
02621             TClass* pClass = 0;
02622             // First check whether this sub-branch is part of the 'cache' (because the data member it
02623             // represent is no longer in the current class layout.
02624             TStreamerInfo *subInfo = subBranch->GetInfoImp();
02625             if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
02626                pClass = ((TStreamerElement*)subInfo->GetElements()->At(0))->GetClassPointer();
02627             }
02628             // FIXME: Do we need the other base class tests here?
02629             if (!pClass) {
02630                if (fType == 1) {
02631                   // -- Parent branch is a base class branch.
02632                   // FIXME: Is using branchElem here the right thing?
02633                   pClass = branchElem->GetClassPointer();
02634                } else {
02635                   // -- Parent branch is *not* a base class branch.
02636                   // FIXME: This sometimes returns a null pointer.
02637                   pClass = subBranch->GetParentClass();
02638                }
02639             }
02640             if (!pClass) {
02641                // -- No parent class, fix it.
02642                // FIXME: This is probably wrong!
02643                // Assume parent class is our parent branch's clones class or value class.
02644                if (GetClonesName() && strlen(GetClonesName())) {
02645                   pClass = TClass::GetClass(GetClonesName());
02646                   if (!pClass) {
02647                      Warning("InitializeOffsets", "subBranch: '%s' has no parent class, and cannot get class for clones class: '%s'!", subBranch->GetName(), GetClonesName());
02648                      fInitOffsets = kTRUE;
02649                      return;
02650                   }
02651                   Warning("InitializeOffsets", "subBranch: '%s' has no parent class!  Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
02652                }
02653                if (fBranchCount && fBranchCount->fCollProxy && fBranchCount->fCollProxy->GetValueClass()) {
02654                   pClass = fBranchCount->fCollProxy->GetValueClass();
02655                   Warning("InitializeOffsets", "subBranch: '%s' has no parent class!  Assuming parent class is: '%s'.", subBranch->GetName(), pClass ? pClass->GetName() : "unknowned class");
02656                }
02657                if (!pClass) {
02658                   // -- Still no parent class, assume our parent class is our parent branch's class.
02659                   // FIXME: This is probably wrong!
02660                   pClass = branchClass;
02661                   // FIXME: Enable this warning!
02662                   //Warning("InitializeOffsets", "subBranch: '%s' has no parent class!  Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
02663                }
02664             }
02665 
02666             //------------------------------------------------------------------
02667             // If we have the are the sub-branch of the TBranchSTL, we need
02668             // to remove it's name to get the correct real data offsets
02669             //-----------------------------------------------------------------
02670             if( stlParentName.Length() )
02671             {
02672                if( !strncmp( stlParentName.Data(), dataName.Data(), stlParentName.Length()-1 ))
02673                   dataName.Remove( 0, stlParentName.Length()+1 );
02674             }
02675 
02676             // Find our offset in our parent class using
02677             // a lookup by name in the dictionary meta info
02678             // for our parent class.
02679             TRealData* rd = pClass->GetRealData(dataName);
02680             if (rd && !rd->TestBit(TRealData::kTransient)) {
02681                // -- Data member exists in the dictionary meta info, get the offset.
02682                offset = rd->GetThisOffset();
02683             } else {
02684                // -- No dictionary meta info for this data member, it must no longer exist.
02685                localOffset = TStreamerInfo::kMissing;
02686             }
02687          } else {
02688             // -- We have no data member name, ok for a base class, not good otherwise.
02689             if (isBaseSubBranch) {
02690                // I am a direct base class of my parent class, my local offset is enough.
02691             } else {
02692                Warning("InitializeOffsets", "Could not find the data member name for branch '%s' with parent branch '%s', assuming offset is zero!", subBranch->GetName(), GetName());
02693             }
02694          }
02695 
02696          //
02697          // Ok, do final calculations for fOffset and fBranchOffset.
02698          //
02699 
02700          if (isContDataMember) {
02701             // -- Container data members set fOffset instead of fBranchOffset.
02702             // The fOffset is what should be added to the start of the entry
02703             // in the collection (i.e., its current absolute address) to find
02704             // the beginning of the data member described by the current branch.
02705             //
02706             // Compensate for the i/o routines adding our local offset later.
02707             if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
02708                subBranch->SetOffset(TStreamerInfo::kMissing);
02709             } else {
02710                if (isBaseSubBranch) {
02711                   // The value of 'offset' for a base class does not include its
02712                   // 'localOffset'.
02713                   subBranch->SetOffset(offset);
02714                } else {
02715                   // The value of 'offset' for a regular data member does include its
02716                   // 'localOffset', we need to remove it explicitly.
02717                   subBranch->SetOffset(offset - localOffset);
02718                }
02719             }
02720          } else {
02721             // -- Set fBranchOffset for sub-branch.
02722             Int_t isSplit = 0 != subBranch->GetListOfBranches()->GetEntriesFast();
02723             if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
02724                // The branch is missing
02725                fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
02726 
02727             } else if (isSplit) {
02728                if (isBaseSubBranch) {
02729                   // We are split, so we need to add in our local offset
02730                   // to get our absolute address for our children.
02731                   fBranchOffset[subBranchIdx] = offset + localOffset;
02732                } else {
02733                   // We are split so our offset will never be
02734                   // used in an i/o, so we do not have to subtract
02735                   // off our local offset like below.
02736                   fBranchOffset[subBranchIdx] = offset;
02737                }
02738             } else {
02739                if (isBaseSubBranch) {
02740                   // We are not split, so our local offset will be
02741                   // added later by the i/o routines.
02742                   fBranchOffset[subBranchIdx] = offset;
02743                } else {
02744                   // Compensate for the fact that the i/o routines
02745                   // are going to add my local offset later.
02746                   fBranchOffset[subBranchIdx] = offset - localOffset;
02747                }
02748             }
02749          }
02750       }
02751    }
02752 
02753    fInitOffsets = kTRUE;
02754 }
02755 
02756 //______________________________________________________________________________
02757 Bool_t TBranchElement::IsFolder() const
02758 {
02759    // -- Return kTRUE if more than one leaf, kFALSE otherwise.
02760 
02761    Int_t nbranches = fBranches.GetEntriesFast();
02762    if (nbranches >= 1) {
02763       return kTRUE;
02764    }
02765    TList* browsables = const_cast<TBranchElement*>(this)->GetBrowsables();
02766    return browsables && browsables->GetSize();
02767 }
02768 
02769 //______________________________________________________________________________
02770 Bool_t TBranchElement::IsMissingCollection() const
02771 {
02772    // -- Detect a collection written using a zero pointer in old versions of root.
02773    // In versions of ROOT older than 4.00/03, if a collection (TClonesArray
02774    // or STL container) was split but the pointer to the collection was zeroed
02775    // out, nothing was saved.  Hence there is no __easy__ way to detect the
02776    // case.  In newer versions, a zero is written so that a 'missing' collection
02777    // appears to be an empty collection.
02778 
02779    Bool_t ismissing = kFALSE;
02780    TBasket* basket = (TBasket*) fBaskets.UncheckedAt(fReadBasket);
02781    if (basket && fTree) {
02782       Int_t entry = fTree->GetReadEntry();
02783       Int_t first  = fBasketEntry[fReadBasket];
02784       Int_t last;
02785       if (fReadBasket == fWriteBasket) {
02786          last = fEntryNumber - 1;
02787       } else {
02788          last = fBasketEntry[fReadBasket+1] - 1;
02789       }
02790       Int_t* entryOffset = basket->GetEntryOffset();
02791       Int_t bufbegin;
02792       Int_t bufnext;
02793       if (entryOffset) {
02794          bufbegin = entryOffset[entry-first];
02795 
02796          if (entry < last) {
02797             bufnext = entryOffset[entry+1-first];
02798          } else {
02799             bufnext = basket->GetLast();
02800          }
02801          if (bufnext == bufbegin) {
02802             ismissing = kTRUE;
02803          } else {
02804             // fixed length buffer so this is not the case here.
02805             if (basket->GetNevBufSize() == 0) {
02806                ismissing = kTRUE;
02807             }
02808          }
02809       }
02810    }
02811    return ismissing;
02812 }
02813 
02814 //______________________________________________________________________________
02815 void TBranchElement::Print(Option_t* option) const
02816 {
02817    // Print branch parameters.
02818 
02819    Int_t nbranches = fBranches.GetEntriesFast();
02820    if (strncmp(option,"debugAddress",strlen("debugAddress"))==0) {
02821       if (strlen(option)==strlen("debugAddress")) {
02822          Printf("%-24s %-16s %2s %4s %-16s %-16s %8s %8s %s\n",
02823                 "Branch Name", "Streamer Class", "ID", "Type", "Class", "Parent", "pOffset", "fOffset", "fObject");
02824       }
02825       if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
02826       else Printf("%-24s ", GetName());
02827 
02828       TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
02829       Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
02830       TVirtualStreamerInfo *info = ((TBranchElement*)this)->GetInfoImp();
02831 
02832       Printf("%-16s %2d %4d %-16s %-16s %8x %8x %s\n",
02833              info ? info->GetName() : "StreamerInfo unvailable", GetID(), GetType(),
02834              GetClassName(), GetParentName(),
02835              (fBranchOffset&&parent && ind>=0) ? parent->fBranchOffset[ind] : 0,
02836              GetOffset(), GetObject());
02837       for (Int_t i = 0; i < nbranches; ++i) {
02838          TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
02839          subbranch->Print("debugAddressSub");
02840       }
02841       return;
02842    }
02843    if (strncmp(option,"debugInfo",strlen("debugInfo"))==0)  {
02844       Printf("Branch %s uses:\n",GetName());
02845       if (fID>=0) {
02846          ULong_t* elems = GetInfoImp()->GetElems();
02847          ((TStreamerElement*) elems[fID])->ls();
02848          for(UInt_t i=0; i< fIDs.size(); ++i) {
02849             ((TStreamerElement*) elems[fIDs[i]])->ls();
02850          }
02851       }
02852       for (Int_t i = 0; i < nbranches; ++i) {
02853          TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
02854          subbranch->Print("debugInfoSub");
02855       }
02856       return;
02857    }
02858    if (nbranches) {
02859       if (fID == -2) {
02860          if (strcmp(GetName(),GetTitle()) == 0) {
02861             Printf("*Branch  :%-66s *",GetName());
02862          } else {
02863             Printf("*Branch  :%-9s : %-54s *",GetName(),GetTitle());
02864          }
02865          Printf("*Entries : %8d : BranchElement (see below)                              *",Int_t(fEntries));
02866          Printf("*............................................................................*");
02867       }
02868       if (fType >= 2) {
02869          TBranch::Print(option);
02870       }
02871       for (Int_t i=0;i<nbranches;i++) {
02872          TBranch *branch = (TBranch*)fBranches.At(i);
02873          branch->Print(option);
02874       }
02875    } else {
02876       TBranch::Print(option);
02877    }
02878 }
02879 
02880 //______________________________________________________________________________
02881 void TBranchElement::PrintValue(Int_t lenmax) const
02882 {
02883    // -- Prints values of leaves.
02884 
02885    ValidateAddress();
02886 
02887    TStreamerInfo *info = GetInfoImp();
02888    Int_t prID = fID;
02889    char *object = fObject;
02890    if (TestBit(kCache)) {
02891       if (info->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
02892          prID = fID+1;
02893       } else if (fOnfileObject) {
02894          object = fOnfileObject->GetObjectAt(0);
02895       }
02896    }
02897 
02898    if (fTree->GetMakeClass()) {
02899       if (!fAddress) {
02900          return;
02901       }
02902       if (fType == 3 || fType == 4) {
02903          // TClonesArray or STL container top-level branch.
02904          printf(" %-15s = %d\n", GetName(), fNdata);
02905          return;
02906       } else if (fType == 31 || fType == 41) {
02907          // TClonesArray or STL container sub-branch.
02908          Int_t n = TMath::Min(10, fNdata);
02909          Int_t atype = fStreamerType + TVirtualStreamerInfo::kOffsetL;
02910          if (fStreamerType == TVirtualStreamerInfo::kChar) {
02911             // TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar is
02912             // printed as a string and could print weird characters.
02913             // So we print an unsigned char instead (not perfect, but better).
02914             atype = TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar;
02915          }
02916          if (atype > 54) {
02917             // FIXME: More logic required here (like in ReadLeaves)
02918             printf(" %-15s = %d\n", GetName(), fNdata);
02919             return;
02920          }
02921          if (fStreamerType > 20) {
02922             atype -= 20;
02923             TLeafElement* leaf = (TLeafElement*) fLeaves.UncheckedAt(0);
02924             n = n * leaf->GetLenStatic();
02925          }
02926          if (GetInfoImp()) {
02927             GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
02928          }
02929          return;
02930       } else if (fType <= 2) {
02931          // Branch in split mode.
02932          // FIXME: This should probably be < 60 instead.
02933          if ((fStreamerType > 40) && (fStreamerType < 55)) {
02934             Int_t atype = fStreamerType - 20;
02935             TBranchElement* counterElement = (TBranchElement*) fBranchCount;
02936             Int_t n = (Int_t) counterElement->GetValue(0, 0);
02937             if (GetInfoImp()) {
02938                GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
02939             }
02940          } else {
02941             if (GetInfoImp()) {
02942                GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
02943             }
02944          }
02945          return;
02946       }
02947    } else if (fType == 3) {
02948       printf(" %-15s = %d\n", GetName(), fNdata);
02949    } else if (fType == 31) {
02950       TClonesArray* clones = (TClonesArray*) object;
02951       if (GetInfoImp()) {
02952          GetInfoImp()->PrintValueClones(GetName(), clones, prID, fOffset, lenmax);
02953       }
02954    } else if (fType == 41) {
02955       TVirtualCollectionProxy::TPushPop helper(((TBranchElement*) this)->GetCollectionProxy(), object);
02956       if (GetInfoImp()) {
02957          GetInfoImp()->PrintValueSTL(GetName(), ((TBranchElement*) this)->GetCollectionProxy(), prID, fOffset, lenmax);
02958       }
02959    } else {
02960       if (GetInfoImp()) {
02961          GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
02962       }
02963    }
02964 }
02965 
02966 //______________________________________________________________________________
02967 void  TBranchElement::ReadLeavesImpl(TBuffer&)
02968 {
02969    // -- Unconfiguration Read Leave function.
02970    
02971    Fatal("ReadLeaves","The ReadLeaves function has not been configured for %s",GetName());
02972 }
02973 
02974 //______________________________________________________________________________
02975 void TBranchElement::ReadLeavesMakeClass(TBuffer& b)
02976 {
02977    // -- Read leaves into i/o buffers for this branch.
02978    // For the case where the branch is set in MakeClass mode (decomposed object).
02979 
02980    ValidateAddress();
02981    
02982    if (fType == 3 || fType == 4) {
02983       // Top level branch of a TClonesArray.
02984       Int_t *n = (Int_t*) fAddress;
02985       b >> n[0];
02986       if ((n[0] < 0) || (n[0] > fMaximum)) {
02987          if (IsMissingCollection()) {
02988             n[0] = 0;
02989             b.SetBufferOffset(b.Length() - sizeof(n));
02990          } else {
02991             Error("ReadLeaves", "Incorrect size read for the container in %s\nThe size read is %d when the maximum is %d\nThe size is reset to 0 for this entry (%lld)", GetName(), n[0], fMaximum, GetReadEntry());
02992             n[0] = 0;
02993          }
02994       }
02995       fNdata = n[0];
02996       if (fType == 4)   {
02997          Int_t nbranches = fBranches.GetEntriesFast();
02998          switch(fSTLtype) {
02999             case TClassEdit::kSet:
03000             case TClassEdit::kMultiSet:
03001             case TClassEdit::kMap:
03002             case TClassEdit::kMultiMap:
03003                for (Int_t i=0; i<nbranches; i++) {
03004                   TBranch *branch = (TBranch*)fBranches[i];
03005                   Int_t nb = branch->GetEntry(GetReadEntry(), 1);
03006                   if (nb < 0) {
03007                      break;
03008                   }
03009                }
03010                break;
03011             default:
03012                break;
03013          }
03014       }
03015       return;
03016    } else if (fType == 31 || fType == 41) {    // sub branch of a TClonesArray
03017       fNdata = fBranchCount->GetNdata();
03018       Int_t atype = fStreamerType;
03019       // FIXME: This should probably be > 59 instead.
03020       if (atype > 54) return;
03021       if (!fAddress) {
03022          return;
03023       }
03024       Int_t n = fNdata;
03025       if (atype>40) {
03026          atype -= 40;
03027          if (!fBranchCount2) return;
03028          const char *len_where = (char*)fBranchCount2->fAddress;
03029          if (!len_where) return;
03030          Int_t len_atype = fBranchCount2->fStreamerType;
03031          Int_t length;
03032          Int_t k;
03033          Char_t isArray;
03034          for( k=0; k<n; k++) {
03035             char **where = &(((char**)fAddress)[k]);
03036             delete [] *where;
03037             *where = 0;
03038             switch(len_atype) {
03039                case  1:  {length = ((Char_t*)   len_where)[k]; break;}
03040                case  2:  {length = ((Short_t*)  len_where)[k]; break;}
03041                case  3:  {length = ((Int_t*)    len_where)[k]; break;}
03042                case  4:  {length = ((Long_t*)   len_where)[k]; break;}
03043                   //case  5:  {length = ((Float_t*) len_where)[k]; break;}
03044                case  6:  {length = ((Int_t*)    len_where)[k]; break;}
03045                   //case  8:  {length = ((Double_t*)len_where)[k]; break;}
03046                case 11:  {length = ((UChar_t*)  len_where)[k]; break;}
03047                case 12:  {length = ((UShort_t*) len_where)[k]; break;}
03048                case 13:  {length = ((UInt_t*)   len_where)[k]; break;}
03049                case 14:  {length = ((ULong_t*)  len_where)[k]; break;}
03050                case 15:  {length = ((UInt_t*)   len_where)[k]; break;}
03051                case 16:  {length = ((Long64_t*) len_where)[k]; break;}
03052                case 17:  {length = ((ULong64_t*)len_where)[k]; break;}
03053                case 18:  {length = ((Bool_t*)   len_where)[k]; break;}
03054                default: continue;
03055             }
03056             b >> isArray;
03057             if (length <= 0)  continue;
03058             if (isArray == 0) continue;
03059             switch (atype) {
03060                case  1:  {*where=new char[sizeof(Char_t)*length]; b.ReadFastArray((Char_t*) *where, length); break;}
03061                case  2:  {*where=new char[sizeof(Short_t)*length]; b.ReadFastArray((Short_t*) *where, length); break;}
03062                case  3:  {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*)   *where, length); break;}
03063                case  4:  {*where=new char[sizeof(Long_t)*length]; b.ReadFastArray((Long_t*)  *where, length); break;}
03064                case  5:  {*where=new char[sizeof(Float_t)*length]; b.ReadFastArray((Float_t*) *where, length); break;}
03065                case  6:  {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*)   *where, length); break;}
03066                case  8:  {*where=new char[sizeof(Double_t)*length]; b.ReadFastArray((Double_t*)*where, length); break;}
03067                case 11:  {*where=new char[sizeof(UChar_t)*length]; b.ReadFastArray((UChar_t*) *where, length); break;}
03068                case 12:  {*where=new char[sizeof(UShort_t)*length]; b.ReadFastArray((UShort_t*)*where, length); break;}
03069                case 13:  {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*)  *where, length); break;}
03070                case 14:  {*where=new char[sizeof(ULong_t)*length]; b.ReadFastArray((ULong_t*) *where, length); break;}
03071                case 15:  {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*)  *where, length); break;}
03072                case 16:  {*where=new char[sizeof(Long64_t)*length]; b.ReadFastArray((Long64_t*)  *where, length); break;}
03073                case 17:  {*where=new char[sizeof(ULong64_t)*length]; b.ReadFastArray((ULong64_t*)*where, length); break;}
03074                case 18:  {*where=new char[sizeof(Bool_t)*length]; b.ReadFastArray((Bool_t*) *where, length); break;}
03075             }
03076          }
03077          return;
03078       }
03079       if (atype > 20) {
03080          atype -= 20;
03081          TLeafElement *leaf = (TLeafElement*)fLeaves.UncheckedAt(0);
03082          n *= leaf->GetLenStatic();
03083       }
03084       switch (atype) {
03085          case  1:  {b.ReadFastArray((Char_t*)  fAddress, n); break;}
03086          case  2:  {b.ReadFastArray((Short_t*) fAddress, n); break;}
03087          case  3:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
03088          case  4:  {b.ReadFastArray((Long_t*)  fAddress, n); break;}
03089          case  5:  {b.ReadFastArray((Float_t*) fAddress, n); break;}
03090          case  6:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
03091          case  8:  {b.ReadFastArray((Double_t*)fAddress, n); break;}
03092          case 11:  {b.ReadFastArray((UChar_t*) fAddress, n); break;}
03093          case 12:  {b.ReadFastArray((UShort_t*)fAddress, n); break;}
03094          case 13:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
03095          case 14:  {b.ReadFastArray((ULong_t*) fAddress, n); break;}
03096          case 15:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
03097          case 16:  {b.ReadFastArray((Long64_t*)fAddress, n); break;}
03098          case 17:  {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
03099          case 18:  {b.ReadFastArray((Bool_t*)  fAddress, n); break;}
03100          case  9:  {
03101             TVirtualStreamerInfo* si = GetInfoImp();
03102             TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
03103             Double_t *xx = (Double_t*) fAddress;
03104             for (Int_t ii=0;ii<n;ii++) {
03105                b.ReadDouble32(&(xx[ii]),se);
03106             }
03107             break;
03108          }
03109          case  19:  {
03110             TVirtualStreamerInfo* si = GetInfoImp();
03111             TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
03112             Float_t *xx = (Float_t*) fAddress;
03113             for (Int_t ii=0;ii<n;ii++) {
03114                b.ReadFloat16(&(xx[ii]),se);
03115             }
03116             break;
03117          }
03118       }
03119       return;
03120    } else if (fType <= 2) {     // branch in split mode
03121       // FIXME: This should probably be < 60 instead.
03122       if (fStreamerType > 40 && fStreamerType < 55) {
03123          Int_t atype = fStreamerType - 40;
03124          Int_t n;
03125          if (fBranchCount==0) {
03126             // Missing fBranchCount.  let's attempts to recover.
03127             
03128             TString countname( GetName() );
03129             Ssiz_t dot = countname.Last('.');
03130             if (dot>=0) {
03131                countname.Remove(dot+1);
03132             } else {
03133                countname = "";
03134             }
03135             TString counter( GetTitle() );
03136             Ssiz_t loc = counter.Last('[');
03137             if (loc>=0) {
03138                counter.Remove(0,loc+1);
03139             }
03140             loc = counter.Last(']');
03141             if (loc>=0) {
03142                counter.Remove(loc);
03143             }
03144             countname += counter;
03145             SetBranchCount((TBranchElement *)fTree->GetBranch(countname));
03146          }
03147          if (fBranchCount) {
03148             n = (Int_t)fBranchCount->GetValue(0,0);
03149          } else {
03150             Warning("ReadLeaves","Missing fBranchCount for %s.  Data will not be read correctly by the MakeClass mode.",GetName());
03151             n = 0;
03152          }
03153          fNdata = n;
03154          Char_t isArray;
03155          b >> isArray;
03156          switch (atype) {
03157             case  1:  {b.ReadFastArray((Char_t*)  fAddress, n); break;}
03158             case  2:  {b.ReadFastArray((Short_t*) fAddress, n); break;}
03159             case  3:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
03160             case  4:  {b.ReadFastArray((Long_t*)  fAddress, n); break;}
03161             case  5:  {b.ReadFastArray((Float_t*) fAddress, n); break;}
03162             case  6:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
03163             case  8:  {b.ReadFastArray((Double_t*)fAddress, n); break;}
03164             case 11:  {b.ReadFastArray((UChar_t*) fAddress, n); break;}
03165             case 12:  {b.ReadFastArray((UShort_t*)fAddress, n); break;}
03166             case 13:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
03167             case 14:  {b.ReadFastArray((ULong_t*) fAddress, n); break;}
03168             case 15:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
03169             case 16:  {b.ReadFastArray((Long64_t*) fAddress, n); break;}
03170             case 17:  {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
03171             case 18:  {b.ReadFastArray((Bool_t*)   fAddress, n); break;}
03172             case  9:  {
03173                TVirtualStreamerInfo* si = GetInfoImp();
03174                TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
03175                Double_t *xx = (Double_t*) fAddress;
03176                for (Int_t ii=0;ii<n;ii++) {
03177                   b.ReadDouble32(&(xx[ii]),se);
03178                }
03179                break;
03180             }
03181             case  19:  {
03182                TVirtualStreamerInfo* si = GetInfoImp();
03183                TStreamerElement* se = (TStreamerElement*) si->GetElems()[fID];
03184                Float_t *xx = (Float_t*) fAddress;
03185                for (Int_t ii=0;ii<n;ii++) {
03186                   b.ReadFloat16(&(xx[ii]),se);
03187                }
03188                break;
03189             }
03190          }
03191       } else {
03192          fNdata = 1;
03193          if (fAddress) {
03194             if (fType<0) {
03195                // Non TObject, Non collection classes with a custom streamer.
03196                
03197                // if (fObject)
03198                fBranchClass->Streamer(fObject,b);
03199             } else {
03200                GetInfoImp()->ReadBuffer(b, (char**) &fObject, fID);
03201             }
03202             if (fStreamerType == TVirtualStreamerInfo::kCounter) {
03203                fNdata = (Int_t) GetValue(0, 0);
03204             }
03205          } else {
03206             fNdata = 0;
03207          }
03208       }
03209       return;
03210    }
03211 }
03212 
03213 //______________________________________________________________________________
03214 void TBranchElement::ReadLeavesCollection(TBuffer& b)
03215 {
03216    // -- Read leaves into i/o buffers for this branch.
03217    // Case of a collection (fType == 4).
03218    
03219    ValidateAddress();
03220    if (fObject == 0)
03221    {
03222       // We have nowhere to copy the data (probably because the data member was
03223       // 'dropped' from the current schema) so let's no copy it in a random place.
03224       return;
03225    }
03226    
03227    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03228    
03229    // STL container master branch (has only the number of elements).
03230    Int_t n;
03231    b >> n;
03232    if ((n < 0) || (n > fMaximum)) {
03233       if (IsMissingCollection()) {
03234          n = 0;
03235          b.SetBufferOffset(b.Length()-sizeof(n));
03236       } else {
03237          Error("ReadLeaves", "Incorrect size read for the container in %s\n\tThe size read is %d while the maximum is %d\n\tThe size is reset to 0 for this entry (%lld)", GetName(), n, fMaximum, GetReadEntry());
03238          n = 0;
03239       }
03240    }
03241    fNdata = n;
03242    if (!fObject) {
03243       return;
03244    }
03245    // Note: Proxy-helper needs to "embrace" the entire
03246    //       streaming of this STL container if the container
03247    //       is a set/multiset/map/multimap (what we do not
03248    //       know here).
03249    //       For vector/list/deque Allocate == Resize
03250    //                         and Commit   == noop.
03251    // TODO: Exception safety a la TPushPop
03252    TVirtualCollectionProxy* proxy = GetCollectionProxy();
03253    TVirtualCollectionProxy::TPushPop helper(proxy, fObject);
03254    void* alternate = proxy->Allocate(fNdata, true);   
03255    if(fSTLtype != TClassEdit::kVector && proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
03256       fPtrIterators->CreateIterators(alternate);
03257    } else {
03258       fIterators->CreateIterators(alternate);
03259    }      
03260    
03261    Int_t nbranches = fBranches.GetEntriesFast();
03262    switch (fSTLtype) {
03263       case TClassEdit::kSet:
03264       case TClassEdit::kMultiSet:
03265       case TClassEdit::kMap:
03266       case TClassEdit::kMultiMap:
03267          for (Int_t i = 0; i < nbranches; ++i) {
03268             TBranch *branch = (TBranch*) fBranches[i];
03269             Int_t nb = branch->GetEntry(GetReadEntry(), 1);
03270             if (nb < 0) {
03271                // Give up on i/o failure.
03272                // FIXME: We need an error message here.
03273                break;
03274             }
03275          }
03276          break;
03277       default:
03278          break;
03279    }
03280    //------------------------------------------------------------------------
03281    // We have split this stuff, so we need to create the the pointers
03282    //-----------------------------------------------------------------------
03283    if( proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers )
03284    {
03285       TClass *elClass = proxy->GetValueClass();
03286       
03287       //--------------------------------------------------------------------
03288       // The allocation is done in this strange way because ReadLeaves
03289       // is being called many times by TTreeFormula!!!
03290       //--------------------------------------------------------------------
03291       Int_t i = 0;
03292       if( !fNdata || *(void**)proxy->At( 0 ) != 0 )
03293          i = fNdata;
03294       
03295       for( ; i < fNdata; ++i )
03296       {
03297          void **el = (void**)proxy->At( i );
03298          // coverity[dereference] since this is a member streaming action by definition the collection contains objects and elClass is not null.
03299          *el = elClass->New();
03300       }
03301    }
03302    
03303    proxy->Commit(alternate);   
03304 }
03305 
03306 //______________________________________________________________________________
03307 void TBranchElement::ReadLeavesCollectionSplitPtrMember(TBuffer& b)
03308 {
03309    // -- Read leaves into i/o buffers for this branch.
03310    // Case of a data member within a collection (fType == 41).
03311    
03312    ValidateAddress();   
03313    if (fObject == 0)
03314    {
03315       // We have nowhere to copy the data (probably because the data member was
03316       // 'dropped' from the current schema) so let's no copy it in a random place.
03317       return;
03318    }
03319    
03320    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03321    
03322    // STL container sub-branch (contains the elements).
03323    fNdata = fBranchCount->GetNdata();
03324    if (!fNdata || !fObject) {
03325       return;
03326    }
03327    TStreamerInfo *info = GetInfoImp();
03328    if (info == 0) return;
03329    
03330    TVirtualCollectionProxy *proxy = GetCollectionProxy();
03331    TVirtualCollectionProxy::TPushPop helper(proxy, fObject);
03332    
03333    // R__ASSERT(0);
03334    TVirtualCollectionPtrIterators *iter = fBranchCount->fPtrIterators;
03335    b.ReadSequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
03336    
03337    //   char **arr = (char **)proxy->At(0);
03338    //   char **end = arr + proxy->Size();
03339    //   fReadActionSequence->ReadBufferVecPtr(b,arr,end);
03340    
03341    //   info->ReadBufferSTLPtrs(b, proxy, fNdata, fID, fOffset);
03342    //   for(UInt_t ii=0; ii < fIDs.size(); ++ii) {
03343    //      info->ReadBufferSTLPtrs(b, proxy, fNdata, fIDs[ii], fOffset);
03344    //   }
03345 }
03346 
03347 //______________________________________________________________________________
03348 void TBranchElement::ReadLeavesCollectionSplitVectorPtrMember(TBuffer& b)
03349 {
03350    // -- Read leaves into i/o buffers for this branch.
03351    // Case of a data member within a collection (fType == 41).
03352    
03353    ValidateAddress();   
03354    if (fObject == 0)
03355    {
03356       // We have nowhere to copy the data (probably because the data member was
03357       // 'dropped' from the current schema) so let's no copy it in a random place.
03358       return;
03359    }
03360    
03361    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03362    
03363    // STL container sub-branch (contains the elements).
03364    fNdata = fBranchCount->GetNdata();
03365    if (!fNdata || !fObject) {
03366       return;
03367    }
03368    TStreamerInfo *info = GetInfoImp();
03369    if (info == 0) return;
03370    
03371    TVirtualCollectionProxy *proxy = GetCollectionProxy();
03372    TVirtualCollectionProxy::TPushPop helper(proxy, fObject);
03373    
03374 
03375    TVirtualCollectionIterators *iter = fBranchCount->fIterators;
03376    b.ReadSequenceVecPtr(*fReadActionSequence,iter->fBegin,iter->fEnd);
03377 }
03378 
03379 //______________________________________________________________________________
03380 void TBranchElement::ReadLeavesCollectionMember(TBuffer& b)
03381 {
03382    // -- Read leaves into i/o buffers for this branch.
03383    // Case of a data member within a collection (fType == 41).
03384    
03385    ValidateAddress();
03386    if (fObject == 0)
03387    {
03388       // We have nowhere to copy the data (probably because the data member was
03389       // 'dropped' from the current schema) so let's no copy it in a random place.
03390       return;
03391    }
03392 
03393    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03394 
03395    // STL container sub-branch (contains the elements).
03396    fNdata = fBranchCount->GetNdata();
03397    if (!fNdata || !fObject) {
03398       return;
03399    }
03400    TStreamerInfo *info = GetInfoImp();
03401    if (info == 0) return;
03402    // Since info is not null, fReadActionSequence is not null either.
03403 
03404    // Still calling PushPop for the legacy entries.
03405    TVirtualCollectionProxy *proxy = GetCollectionProxy();
03406    TVirtualCollectionProxy::TPushPop helper(proxy, fObject);
03407    
03408    TVirtualCollectionIterators *iter = fBranchCount->fIterators;
03409    b.ReadSequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
03410 }
03411 
03412 //______________________________________________________________________________
03413 void TBranchElement::ReadLeavesClones(TBuffer& b)
03414 {
03415    // -- Read leaves into i/o buffers for this branch.
03416    // Case of a TClonesArray (fType == 3).
03417    
03418    ValidateAddress();
03419    if (fObject == 0)
03420    {
03421       // We have nowhere to copy the data (probably because the data member was
03422       // 'dropped' from the current schema) so let's no copy it in a random place.
03423       return;
03424    }
03425 
03426    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03427    
03428    // TClonesArray master branch (has only the number of elements).
03429    Int_t n;
03430    b >> n;
03431    if ((n < 0) || (n > fMaximum)) {
03432       if (IsMissingCollection()) {
03433          n = 0;
03434          b.SetBufferOffset(b.Length()-sizeof(n));
03435       } else {
03436          Error("ReadLeaves", "Incorrect size read for the container in %s\n\tThe size read is %d while the maximum is %d\n\tThe size is reset to 0 for this entry (%lld)", GetName(), n, fMaximum, GetReadEntry());
03437          n = 0;
03438       }
03439    }
03440    fNdata = n;
03441    TClonesArray* clones = (TClonesArray*) fObject;
03442    if (!clones) {
03443       return;
03444    }
03445    if (clones->IsZombie()) {
03446       return;
03447    }
03448    clones->Clear();
03449    clones->ExpandCreateFast(fNdata);   
03450 }
03451    
03452 //______________________________________________________________________________
03453 void TBranchElement::ReadLeavesClonesMember(TBuffer& b)
03454 {
03455    // -- Read leaves into i/o buffers for this branch.
03456    // Case of a data member within a TClonesArray (fType == 31).
03457    
03458    ValidateAddress();
03459    
03460    if (fObject == 0)
03461    {
03462       // We have nowhere to copy the data (probably because the data member was
03463       // 'dropped' from the current schema) so let's no copy it in a random place.
03464       return;
03465    }
03466 
03467    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03468 
03469    // TClonesArray sub-branch (contains the elements).
03470    fNdata = fBranchCount->GetNdata();
03471    TClonesArray* clones = (TClonesArray*) fObject;
03472    if (!clones) {
03473       return;
03474    }
03475    if (clones->IsZombie()) {
03476       return;
03477    }
03478    TStreamerInfo *info = GetInfoImp();
03479    if (info==0) return;
03480    // Since info is not null, fReadActionSequence is not null either.
03481    
03482    char **arr = (char **)clones->GetObjectRef(0);
03483    char **end = arr + fNdata;
03484    b.ReadSequenceVecPtr(*fReadActionSequence,arr,end);
03485 }
03486 
03487 //______________________________________________________________________________
03488 void TBranchElement::ReadLeavesMember(TBuffer& b)
03489 {
03490    // -- Read leaves into i/o buffers for this branch.
03491    // For split-class branch, base class branch, data member branch, or top-level branch.
03492    // which do not have a branch count and are not a counter.
03493    
03494    R__ASSERT(fBranchCount==0);
03495    R__ASSERT(fStreamerType != TVirtualStreamerInfo::kCounter);
03496    
03497    ValidateAddress();
03498    if (fObject == 0)
03499    {
03500       // We have nowhere to copy the data (probably because the data member was
03501       // 'dropped' from the current schema) so let's no copy it in a random place.
03502       return;
03503    }
03504 
03505    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03506    // If not a TClonesArray or STL container master branch
03507    // or sub-branch and branch inherits from tobject,
03508    // then register with the buffer so that pointers are
03509    // handled properly.
03510    if (TestBit(kBranchObject)) {
03511       b.MapObject((TObject*) fObject);
03512    } else if (TestBit(kBranchAny)) {
03513       b.MapObject(fObject, fBranchClass);
03514    }
03515    
03516    fNdata = 1;
03517    TStreamerInfo *info = GetInfoImp();
03518    if (!info) {
03519       return;
03520    }
03521    // Since info is not null, fReadActionSequence is not null either.
03522    b.ReadSequence(*fReadActionSequence, fObject);
03523 }
03524 
03525 //______________________________________________________________________________
03526 void TBranchElement::ReadLeavesMemberBranchCount(TBuffer& b)
03527 {
03528    // -- Read leaves into i/o buffers for this branch.
03529    // For split-class branch, base class branch, data member branch, or top-level branch.
03530    // which do have a branch count and are not a counter.
03531    
03532    R__ASSERT(fStreamerType != TVirtualStreamerInfo::kCounter);
03533 
03534    ValidateAddress();
03535    if (fObject == 0)
03536    {
03537       // We have nowhere to copy the data (probably because the data member was
03538       // 'dropped' from the current schema) so let's no copy it in a random place.
03539       return;
03540    }
03541 
03542    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03543    // If not a TClonesArray or STL container master branch
03544    // or sub-branch and branch inherits from tobject,
03545    // then register with the buffer so that pointers are
03546    // handled properly.
03547    if (TestBit(kBranchObject)) {
03548       b.MapObject((TObject*) fObject);
03549    } else if (TestBit(kBranchAny)) {
03550       b.MapObject(fObject, fBranchClass);
03551    }
03552    
03553    fNdata = (Int_t) fBranchCount->GetValue(0, 0);
03554    TStreamerInfo *info = GetInfoImp();
03555    if (!info) {
03556       return;
03557    }
03558    // Since info is not null, fReadActionSequence is not null either.
03559    b.ReadSequence(*fReadActionSequence, fObject);
03560 }
03561 
03562 //______________________________________________________________________________
03563 void TBranchElement::ReadLeavesMemberCounter(TBuffer& b)
03564 {
03565    // -- Read leaves into i/o buffers for this branch.
03566    // For split-class branch, base class branch, data member branch, or top-level branch.
03567    // which do not have a branch count and are a counter.
03568    
03569    ValidateAddress();
03570    if (fObject == 0)
03571    {
03572       // We have nowhere to copy the data (probably because the data member was
03573       // 'dropped' from the current schema) so let's no copy it in a random place.
03574       return;
03575    }
03576 
03577    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03578 
03579    // If not a TClonesArray or STL container master branch
03580    // or sub-branch and branch inherits from tobject,
03581    // then register with the buffer so that pointers are
03582    // handled properly.
03583    if (TestBit(kBranchObject)) {
03584       b.MapObject((TObject*) fObject);
03585    } else if (TestBit(kBranchAny)) {
03586       b.MapObject(fObject, fBranchClass);
03587    }
03588 
03589    TStreamerInfo *info = GetInfoImp();
03590    if (!info) {
03591       return;
03592    }
03593    // Since info is not null, fReadActionSequence is not null either.
03594    b.ReadSequence(*fReadActionSequence, fObject);
03595    fNdata = (Int_t) GetValue(0, 0);
03596 }
03597 
03598 //______________________________________________________________________________
03599 void TBranchElement::ReadLeavesCustomStreamer(TBuffer& b)
03600 {
03601    // -- Read leaves into i/o buffers for this branch.   
03602    // Non TObject, Non collection classes with a custom streamer.
03603    
03604    ValidateAddress();
03605    if (fObject == 0)
03606    {
03607       // We have nowhere to copy the data (probably because the data member was
03608       // 'dropped' from the current schema) so let's no copy it in a random place.
03609       return;
03610    }
03611 
03612    R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject);
03613    fBranchClass->Streamer(fObject,b);
03614 }
03615    
03616 //______________________________________________________________________________
03617 void TBranchElement::ReleaseObject()
03618 {
03619    // -- Delete any object we may have allocated on a previous call to SetAddress.
03620 
03621    if (fObject && TestBit(kDeleteObject)) {
03622       if (IsAutoDelete() && fAddress != (char*)&fObject) {
03623          *((char**) fAddress) = 0;
03624       }
03625       ResetBit(kDeleteObject);
03626       if (fType == 3) {
03627          // -- We are a TClonesArray master branch.
03628          TClonesArray::Class()->Destructor(fObject);
03629          fObject = 0;
03630          if ((fStreamerType == TVirtualStreamerInfo::kObjectp) ||
03631              (fStreamerType == TVirtualStreamerInfo::kObjectP)) {
03632             // -- We are a pointer to a TClonesArray.
03633             // We must zero the pointer in the object.
03634             *((char**) fAddress) = 0;
03635          }
03636       } else if (fType == 4) {
03637          // -- We are an STL container master branch.
03638          TVirtualCollectionProxy* proxy = GetCollectionProxy();
03639          if (!proxy) {
03640             Warning("ReleaseObject", "Cannot delete allocated STL container because I do not have a proxy!  branch: %s", GetName());
03641             fObject = 0;
03642          } else {
03643             proxy->Destructor(fObject);
03644             fObject = 0;
03645          }
03646          if (fStreamerType == TVirtualStreamerInfo::kSTLp) {
03647             // -- We are a pointer to an STL container.
03648             // We must zero the pointer in the object.
03649             *((char**) fAddress) = 0;
03650          }
03651       } else {
03652          // We are *not* a TClonesArray master branch and we are *not* an STL container master branch.
03653          TClass* cl = fBranchClass.GetClass();
03654          if (!cl) {
03655             Warning("ReleaseObject", "Cannot delete allocated object because I cannot instantiate a TClass object for its class!  branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
03656             fObject = 0;
03657          } else {
03658             cl->Destructor(fObject);
03659             fObject = 0;
03660          }
03661       }
03662    }
03663 }
03664 
03665 //______________________________________________________________________________
03666 void TBranchElement::Reset(Option_t* option)
03667 {
03668    // -- Reset a Branch.
03669    //
03670    // Existing i/o buffers are deleted.
03671    // Entries, max and min are reset.
03672    //
03673 
03674    Int_t nbranches = fBranches.GetEntriesFast();
03675    for (Int_t i = 0; i < nbranches; ++i) {
03676       TBranch* branch = (TBranch*) fBranches[i];
03677       branch->Reset(option);
03678    }
03679    fBranchID = -1;
03680    TBranch::Reset(option);
03681 }
03682 
03683 //______________________________________________________________________________
03684 void TBranchElement::ResetAddress()
03685 {
03686    // Set branch address to zero and free all allocated memory.
03687 
03688    for (Int_t i = 0; i < fNleaves; ++i) {
03689       TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
03690       //if (leaf) leaf->SetAddress(0);
03691       leaf->SetAddress(0);
03692    }
03693 
03694    // Note: We *must* do the sub-branches first, otherwise
03695    //       we may delete the object containing the sub-branches
03696    //       before giving them a chance to cleanup.
03697    Int_t nbranches = fBranches.GetEntriesFast();
03698    for (Int_t i = 0; i < nbranches; ++i)  {
03699       TBranch* br = (TBranch*) fBranches[i];
03700       if (br) br->ResetAddress();
03701    }
03702 
03703    //
03704    // SetAddress may have allocated an object.
03705    //
03706 
03707    ReleaseObject();
03708 
03709    ResetBit(kAddressSet);
03710    fAddress = 0;
03711    fObject = 0;
03712 }
03713 
03714 //______________________________________________________________________________
03715 void TBranchElement::ResetDeleteObject()
03716 {
03717    // -- Release ownership of any allocated objects.
03718    //
03719    // Note: This interface was added so that clone trees could
03720    //       be told they do not own the allocated objects.
03721 
03722    ResetBit(kDeleteObject);
03723    Int_t nb = fBranches.GetEntriesFast();
03724    for (Int_t i = 0; i < nb; ++i)  {
03725       TBranch* br = (TBranch*) fBranches[i];
03726       if (br->InheritsFrom(TBranchElement::Class())) {
03727          ((TBranchElement*) br)->ResetDeleteObject();
03728       }
03729    }
03730 }
03731 
03732 //______________________________________________________________________________
03733 void TBranchElement::SetAddress(void* addr)
03734 {
03735    // -- Point this branch at an object.
03736    //
03737    // For a sub-branch, addr is a pointer to the branch object.
03738    //
03739    // For a top-level branch the meaning of addr is as follows:
03740    //
03741    // If addr is zero, then we allocate a branch object
03742    // internally and the branch is the owner of the allocated
03743    // object, not the caller.  However the caller may obtain
03744    // a pointer to the branch object with GetObject().
03745    //
03746    // Example:
03747    //
03748    //    branch->SetAddress(0);
03749    //    Event* event = branch->GetObject();
03750    //    ... Do some work.
03751    //
03752    // If addr is not zero, but the pointer addr points at is
03753    // zero, then we allocate a branch object and set the passed
03754    // pointer to point at the allocated object.  The caller
03755    // owns the allocated object and is responsible for deleting
03756    // it when it is no longer needed.
03757    //
03758    // Example:
03759    //
03760    //    Event* event = 0;
03761    //    branch->SetAddress(&event);
03762    //    ... Do some work.
03763    //    delete event;
03764    //    event = 0;
03765    //
03766    // If addr is not zero and the pointer addr points at is
03767    // also not zero, then the caller has allocated a branch
03768    // object and is asking us to use it.  The caller owns it
03769    // and must delete it when it is no longer needed.
03770    //
03771    // Example:
03772    //
03773    //    Event* event = new Event();
03774    //    branch->SetAddress(&event);
03775    //    ... Do some work.
03776    //    delete event;
03777    //    event = 0;
03778    //
03779    // These rules affect users of TTree::Branch(),
03780    // TTree::SetBranchAddress(), and TChain::SetBranchAddress()
03781    // as well because those routines call this one.
03782    //
03783    // An example of a tree with branches with objects allocated
03784    // and owned by us:
03785    //
03786    //    TFile* f1 = new TFile("myfile_original.root");
03787    //    TTree* t1 = (TTree*) f->Get("MyTree");
03788    //    TFile* f2 = new TFile("myfile_copy.root", "recreate");
03789    //    TTree* t2 = t1->Clone(0);
03790    //    for (Int_t i = 0; i < 10; ++i) {
03791    //       t1->GetEntry(i);
03792    //       t2->Fill();
03793    //    }
03794    //    t2->Write()
03795    //    delete f2;
03796    //    f2 = 0;
03797    //    delete f1;
03798    //    f1 = 0;
03799    //
03800    // An example of a branch with an object allocated by us,
03801    // but owned by the caller:
03802    //
03803    //    TFile* f = new TFile("myfile.root", "recreate");
03804    //    TTree* t = new TTree("t", "A test tree.")
03805    //    Event* event = 0;
03806    //    TBranchElement* br = t->Branch("event.", &event);
03807    //    for (Int_t i = 0; i < 10; ++i) {
03808    //       ... Fill event with meaningful data in some way.
03809    //       t->Fill();
03810    //    }
03811    //    t->Write();
03812    //    delete event;
03813    //    event = 0;
03814    //    delete f;
03815    //    f = 0;
03816    //
03817    // Notice that the only difference between this example
03818    // and the following example is that the event pointer
03819    // is zero when the branch is created.
03820    //
03821    // An example of a branch with an object allocated and
03822    // owned by the caller:
03823    //
03824    //    TFile* f = new TFile("myfile.root", "recreate");
03825    //    TTree* t = new TTree("t", "A test tree.")
03826    //    Event* event = new Event();
03827    //    TBranchElement* br = t->Branch("event.", &event);
03828    //    for (Int_t i = 0; i < 10; ++i) {
03829    //       ... Fill event with meaningful data in some way.
03830    //       t->Fill();
03831    //    }
03832    //    t->Write();
03833    //    delete event;
03834    //    event = 0;
03835    //    delete f;
03836    //    f = 0;
03837    //
03838    // If AutoDelete is on (see TBranch::SetAutoDelete),
03839    // the top level objet will be deleted and recreate
03840    // each time an entry is read, whether or not the
03841    // TTree owns the object.
03842    //
03843 
03844    //
03845    //  Don't bother if we are disabled.
03846    //
03847 
03848    if (TestBit(kDoNotProcess)) {
03849       return;
03850    }
03851 
03852    //
03853    //  FIXME: When would this happen?
03854    //
03855 
03856    if (fType < -1) {
03857       return;
03858    }
03859 
03860    //
03861    //  Special case when called from code generated by TTree::MakeClass.
03862    //
03863 
03864    if (Long_t(addr) == -1) {
03865       // FIXME: Do we have to release an object here?
03866       // ReleaseObject();
03867       fAddress = (char*) -1;
03868       fObject = (char*) -1;
03869       ResetBit(kDeleteObject);
03870       return;
03871    }
03872 
03873    //
03874    //  Reset last read entry number, we have a new user object now.
03875    //
03876 
03877    fReadEntry = -1;
03878 
03879    //
03880    // Make sure our branch class is instantiated.
03881    //
03882    TClass* clOfBranch = fBranchClass.GetClass();
03883    if( fTargetClass.GetClassName()[0] ) {
03884       clOfBranch = fTargetClass;
03885    }
03886 
03887    //
03888    // Try to build the streamer info.
03889    //
03890 
03891    TVirtualStreamerInfo *info = GetInfoImp();
03892 
03893    // FIXME: Warn about failure to get the streamer info here?
03894 
03895    //
03896    // We may have allocated an object last time we were called.
03897    //
03898 
03899    if (fObject && TestBit(kDeleteObject)){
03900       ReleaseObject();
03901    }
03902 
03903    //
03904    //  Remember the pointer to the pointer to our object.
03905    //
03906 
03907    fAddress = (char*) addr;
03908    if (fAddress != (char*)(&fObject)) {
03909       fObject = 0;
03910    }
03911    ResetBit(kDeleteObject);
03912 
03913    //
03914    //  Do special stuff if we got called from a MakeClass class.
03915    //  Allow sub-branches to have independently set addresses.
03916    //
03917 
03918    if (fTree->GetMakeClass()) {
03919       if (fID > -1) {
03920          // We are *not* a top-level branch.
03921          if (!info) {
03922             // No streamer info, give up.
03923             // FIXME: We should have an error message here.
03924             fObject = fAddress;
03925          } else {
03926             // Compensate for the fact that the i/o routines
03927             // will add the streamer offset to the address.
03928             fObject = fAddress - info->GetOffsets()[fID];
03929          }
03930          return;
03931       }
03932    }
03933 
03934    //
03935    //  Check whether the container type is still the same
03936    //  to support schema evolution; what is written on the file
03937    //  may no longer match the class code which is loaded.
03938    //
03939 
03940    if (fType == 3) {
03941       // split TClonesArray, counter/master branch.
03942       TClass* clm = TClass::GetClass(GetClonesName());
03943       if (clm) {
03944          // In case clm derives from an abstract class.
03945          clm->BuildRealData();
03946          clm->GetStreamerInfo();
03947       }
03948       TClass* newType = GetCurrentClass();
03949       if (newType && (newType != TClonesArray::Class())) {
03950          // The data type of the container has changed.
03951          //
03952          // Let's check if it is a compatible type:
03953          Bool_t matched = kFALSE;
03954          if (newType->GetCollectionProxy()) {
03955             TClass *content = newType->GetCollectionProxy()->GetValueClass();
03956             if (clm == content) {
03957                matched = kTRUE;
03958             } else {
03959                Warning("SetAddress", "The type of %s was changed from TClonesArray to %s but the content do not match (was %s)!", GetName(), newType->GetName(), GetClonesName());
03960             }
03961          } else {
03962             Warning("SetAddress", "The type of the %s was changed from TClonesArray to %s but we do not have a TVirtualCollectionProxy for that container type!", GetName(), newType->GetName());
03963          }
03964          if (matched) {
03965             // Change from 3/31 to 4/41
03966             SetType(4);
03967             // Set the proxy.
03968             fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(newType->GetName()));
03969             fCollProxy = newType->GetCollectionProxy()->Generate();
03970 
03971             SwitchContainer(GetListOfBranches());
03972             SetReadLeavesPtr();
03973             
03974             if(fSTLtype != TClassEdit::kVector && fCollProxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
03975                fPtrIterators = new TVirtualCollectionPtrIterators(fCollProxy);
03976             } else {
03977                fIterators = new TVirtualCollectionIterators(fCollProxy);
03978             }
03979          } else {
03980             // FIXME: Must maintain fObject here as well.
03981             fAddress = 0;
03982          }
03983       }
03984    } else if (fType == 4) {
03985       // split STL container, counter/master branch.
03986       TClass* newType = GetCurrentClass();
03987       if (newType && (newType != GetCollectionProxy()->GetCollectionClass())) {
03988          // Let's check if it is a compatible type:
03989          TVirtualCollectionProxy* newProxy = newType->GetCollectionProxy();
03990          TVirtualCollectionProxy* oldProxy = GetCollectionProxy();
03991          if (newProxy && (oldProxy->GetValueClass() == newProxy->GetValueClass()) && ((!oldProxy->GetValueClass() && (oldProxy->GetType() == newProxy->GetType())) || (oldProxy->GetValueClass() && (oldProxy->HasPointers() == newProxy->HasPointers())))) {
03992             if (fSTLtype == TClassEdit::kNotSTL) {
03993                fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(newType->GetName()));
03994             }
03995             delete fCollProxy;
03996             Int_t nbranches = GetListOfBranches()->GetEntries();
03997             fCollProxy = newType->GetCollectionProxy()->Generate();
03998             for (Int_t i = 0; i < nbranches; ++i) {
03999                TBranchElement* br = (TBranchElement*) GetListOfBranches()->UncheckedAt(i);
04000                br->fCollProxy = 0;
04001                if (br->fReadActionSequence) {
04002                   br->SetReadActionSequence();
04003                }
04004             }
04005             SetReadActionSequence();
04006             SetReadLeavesPtr();
04007             delete fIterators;
04008             delete fPtrIterators;
04009             if(fSTLtype != TClassEdit::kVector && fCollProxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
04010                fPtrIterators = new TVirtualCollectionPtrIterators(fCollProxy);
04011             } else {
04012                fIterators = new TVirtualCollectionIterators(fCollProxy);
04013             }
04014          } 
04015          else if ((newType == TClonesArray::Class()) && (oldProxy->GetValueClass() && !oldProxy->HasPointers() && oldProxy->GetValueClass()->InheritsFrom(TObject::Class()))) 
04016          {            
04017             // The new collection and the old collection are not compatible,
04018             // we cannot use the new collection to read the data.
04019             // Actually we could check if the new collection is a
04020             // compatible ROOT collection.
04021             
04022             // We cannot insure that the TClonesArray is set for the
04023             // proper class (oldProxy->GetValueClass()), so we assume that
04024             // the transformation was done properly by the class designer.
04025             
04026             // Change from 4/41 to 3/31
04027             SetType(3);
04028             // Reset the proxy.
04029             fSTLtype = kNone;
04030             switch(fStreamerType) {
04031                case TVirtualStreamerInfo::kAny:
04032                case TVirtualStreamerInfo::kSTL:
04033                   fStreamerType = TVirtualStreamerInfo::kObject;
04034                   break;
04035                case TVirtualStreamerInfo::kAnyp:
04036                case TVirtualStreamerInfo::kSTLp:
04037                   fStreamerType = TVirtualStreamerInfo::kObjectp;
04038                   break;
04039                case TVirtualStreamerInfo::kAnyP:
04040                   fStreamerType = TVirtualStreamerInfo::kObjectP;
04041                   break;
04042             }
04043             fClonesName = oldProxy->GetValueClass()->GetName();
04044             delete fCollProxy;
04045             fCollProxy = 0;
04046             TClass* clm = TClass::GetClass(GetClonesName());
04047             if (clm) {
04048                clm->BuildRealData(); //just in case clm derives from an abstract class
04049                clm->GetStreamerInfo();
04050             }
04051             SwitchContainer(GetListOfBranches());
04052             SetReadLeavesPtr();
04053             delete fIterators;
04054             fIterators = 0;
04055             delete fPtrIterators;
04056             fPtrIterators =0;
04057          } else {
04058             // FIXME: We must maintain fObject here as well.
04059             fAddress = 0;
04060          }
04061       } else {
04062          if (!fIterators && !fPtrIterators) {
04063             if(fSTLtype != TClassEdit::kVector && GetCollectionProxy()->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
04064                fPtrIterators = new TVirtualCollectionPtrIterators(GetCollectionProxy());
04065             } else {
04066                fIterators = new TVirtualCollectionIterators(GetCollectionProxy());
04067             }
04068          }
04069       }
04070    }
04071 
04072    //
04073    //  Establish the semantics of fObject and fAddress.
04074    //
04075    //  Top-level branch:
04076    //       fObject is a ptr to the object,
04077    //       fAddress is a ptr to a pointer to the object.
04078    //
04079    //  Sub-branch:
04080    //       fObject is a ptr to the object,
04081    //       fAddress is the same as fObject.
04082    //
04083    //
04084    //  There are special cases for TClonesArray and STL containers.
04085    //  If there is no user-provided object, we allocate one.  We must
04086    //  also initialize any STL container proxy.
04087    //
04088 
04089    if (fType == 3) {
04090       // -- We are a TClonesArray master branch.
04091       if (fAddress) {
04092          // -- We have been given a non-zero address, allocate if necessary.
04093          if (fStreamerType == TVirtualStreamerInfo::kObject) {
04094             // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
04095             // Case of an embedded TClonesArray.
04096             fObject = fAddress;
04097             // Check if it has already been properly built.
04098             TClonesArray* clones = (TClonesArray*) fObject;
04099             if (!clones->GetClass()) {
04100                new(fObject) TClonesArray(GetClonesName());
04101             }
04102          } else {
04103             // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
04104             // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
04105             if ((fStreamerType != -1) &&
04106                 (fStreamerType != TVirtualStreamerInfo::kObjectp) &&
04107                 (fStreamerType != TVirtualStreamerInfo::kObjectP)) {
04108                Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
04109             } else if (fStreamerType == -1) {
04110                // -- We are a top-level branch.
04111                TClonesArray** pp = (TClonesArray**) fAddress;
04112                if (!*pp) {
04113                   // -- Caller wants us to allocate the clones array, but he will own it.
04114                   *pp = new TClonesArray(GetClonesName());
04115                }
04116                fObject = (char*) *pp;
04117             } else {
04118                // -- We are a pointer to a TClonesArray.
04119                // Note: We do this so that the default constructor,
04120                //       or the i/o constructor can be lazy.
04121                TClonesArray** pp = (TClonesArray**) fAddress;
04122                if (!*pp) {
04123                   // -- Caller wants us to allocate the clones array, but he will own it.
04124                   *pp = new TClonesArray(GetClonesName());
04125                }
04126                fObject = (char*) *pp;
04127             }
04128          }
04129       } else {
04130          // -- We have been given a zero address, allocate for top-level only.
04131          if (fStreamerType == TVirtualStreamerInfo::kObject) {
04132             // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
04133             // Case of an embedded TClonesArray.
04134             Error("SetAddress", "Embedded TClonesArray given a zero address for branch '%s'", GetName());
04135          } else {
04136             // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
04137             // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
04138             if ((fStreamerType != -1) &&
04139                 (fStreamerType != TVirtualStreamerInfo::kObjectp) &&
04140                 (fStreamerType != TVirtualStreamerInfo::kObjectP)) {
04141                Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
04142             } else if (fStreamerType == -1) {
04143                // -- We are a top-level branch.
04144                // Idea: Consider making a zero address not allocate.
04145                SetBit(kDeleteObject);
04146                fObject = (char*) new TClonesArray(GetClonesName());
04147                fAddress = (char*) &fObject;
04148             } else {
04149                // -- We are a sub-branch which is a pointer to a TClonesArray.
04150                Error("SetAddress", "Embedded pointer to a TClonesArray given a zero address for branch '%s'", GetName());
04151             }
04152          }
04153       }
04154    } else if (fType == 4) {
04155       // -- We are an STL container master branch.
04156       //
04157       // Initialize fCollProxy.
04158       TVirtualCollectionProxy* proxy = GetCollectionProxy();
04159       if (fAddress) {
04160          // -- We have been given a non-zero address, allocate if necessary.
04161          if ((fStreamerType == TVirtualStreamerInfo::kObject) ||
04162              (fStreamerType == TVirtualStreamerInfo::kAny) ||
04163              (fStreamerType == TVirtualStreamerInfo::kSTL)) {
04164             // We are *not* a top-level branch and we are *not* a pointer to an STL container.
04165             // Case of an embedded STL container.
04166             // Note: We test for the kObject and kAny types to support
04167             //       the (unwise) choice of inheriting from an STL container.
04168             fObject = fAddress;
04169          } else {
04170             // We are either a top-level branch or subbranch which is a pointer to an STL container.
04171             // Streamer type should be -1 (for a top-level branch) or kSTLp here.
04172             if ((fStreamerType != -1) && (fStreamerType != TVirtualStreamerInfo::kSTLp)) {
04173                Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
04174             } else if (fStreamerType == -1) {
04175                // -- We are a top-level branch.
04176                void** pp = (void**) fAddress;
04177                if (!*pp) {
04178                   // -- Caller wants us to allocate the STL container, but he will own it.
04179                   *pp = proxy->New();
04180                   if (!(*pp)) {
04181                      Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
04182                      // FIXME: Should we do this?  Lots of other code wants
04183                      //        fAddress to be zero if no fObject, but is
04184                      //        that a good thing?
04185                      fAddress = 0;
04186                   }
04187                }
04188                fObject = (char*) *pp;
04189             } else {
04190                // -- We are a pointer to an STL container.
04191                // Note: We do this so that the default constructor,
04192                //       or the i/o constructor can be lazy.
04193                void** pp = (void**) fAddress;
04194                if (!*pp) {
04195                   // -- Caller wants us to allocate the STL container, but he will own it.
04196                   *pp = proxy->New();
04197                   if (!(*pp)) {
04198                      Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
04199                      // FIXME: Should we do this?  Lots of other code wants
04200                      //        fAddress to be zero if no fObject, but is
04201                      //        that a good thing?
04202                      fAddress = 0;
04203                   }
04204                }
04205                fObject = (char*) *pp;
04206             }
04207          }
04208       } else {
04209          // -- We have been given a zero address, allocate for top-level only.
04210          if ((fStreamerType == TVirtualStreamerInfo::kObject) ||
04211              (fStreamerType == TVirtualStreamerInfo::kAny) ||
04212              (fStreamerType == TVirtualStreamerInfo::kSTL)) {
04213             // We are *not* a top-level branch and we are *not* a pointer to an STL container.
04214             // Case of an embedded STL container.
04215             // Note: We test for the kObject and kAny types to support
04216             //       the (unwise) choice of inheriting from an STL container.
04217             Error("SetAddress", "Embedded STL container given a zero address for branch '%s'", GetName());
04218          } else {
04219             // We are either a top-level branch or sub-branch which is a pointer to an STL container.
04220             // Streamer type should be -1 (for a top-level branch) or kSTLp here.
04221             if ((fStreamerType != -1) && (fStreamerType != TVirtualStreamerInfo::kSTLp)) {
04222                Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
04223             } else if (fStreamerType == -1) {
04224                // -- We are a top-level branch, allocate.
04225                SetBit(kDeleteObject);
04226                fObject = (char*) proxy->New();
04227                if (fObject) {
04228                   fAddress = (char*) &fObject;
04229                } else {
04230                   Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
04231                   // FIXME: Should we do this?  Lots of other code wants
04232                   //        fAddress to be zero if no fObject, but is
04233                   //        that a good thing?
04234                   fAddress = 0;
04235                }
04236             } else {
04237                // -- We are a sub-branch which is a pointer to an STL container.
04238                Error("SetAddress", "Embedded pointer to an STL container given a zero address for branch '%s'", GetName());
04239             }
04240          }
04241       }
04242    } else if (fType == 41) {
04243       // -- We are an STL container sub-branch.
04244       // Initialize fCollProxy.
04245       GetCollectionProxy();
04246       // We are not at top-level branch.
04247       fObject = fAddress;
04248    } else if (fID < 0) {
04249       // -- We are a top-level branch.
04250       char** pp = (char**) fAddress;
04251       if (pp && *pp) {
04252          // -- Caller provided an i/o buffer for us to use.
04253          fObject = *pp;
04254       } else {
04255          // -- Caller did not provide an i/o buffer for us to use, we must make one for ourselves.
04256          if (clOfBranch) {
04257             if (!pp) {
04258                // -- Caller wants us to own the object.
04259                SetBit(kDeleteObject);
04260             }
04261             fObject = (char*) clOfBranch->New();
04262             if (pp) {
04263                *pp = fObject;
04264             } else {
04265                fAddress = (char*) &fObject;
04266             }
04267          } else {
04268             Error("SetAddress", "I have no TClass for branch %s, so I cannot allocate an I/O buffer!", GetName());
04269             if (pp) {
04270                fObject = 0;
04271                *pp = 0;
04272             }
04273          }
04274       }
04275    } else {
04276       // -- We are *not* a top-level branch.
04277       fObject = fAddress;
04278    }
04279 
04280    if (!info) {
04281       // FIXME: We need and error message here, no streamer info, so cannot set offsets.
04282       return;
04283    }
04284 
04285    // We do this only once because it depends only on
04286    // the type of our object, not on its address.
04287    if (!fInitOffsets) {
04288       InitializeOffsets();
04289    }
04290 
04291    // We are split, recurse down to our sub-branches.
04292    //
04293    // FIXME: This is a tail recursion, we burn stack.
04294    Int_t nbranches = fBranches.GetEntriesFast();
04295    for (Int_t i = 0; i < nbranches; ++i) {
04296       TBranch* abranch = (TBranch*) fBranches.UncheckedAt(i);
04297       // FIXME: This is a tail recursion!
04298       if (fBranchOffset[i] != TStreamerInfo::kMissing) {
04299          abranch->SetAddress(fObject + fBranchOffset[i]);
04300          abranch->SetBit(kAddressSet);
04301       } else {
04302          // When the member is missing, just leave the address alone
04303          // (since setting explicitly to 0 would trigger error/warning
04304          // messages).
04305          // abranch->SetAddress(0);
04306          abranch->SetBit(kAddressSet);
04307       }
04308    }
04309 }
04310 
04311 //______________________________________________________________________________
04312 void TBranchElement::SetBasketSize(Int_t buffsize)
04313 {
04314    // -- Reset the basket size for all sub-branches of this branch element.
04315 
04316    TBranch::SetBasketSize(buffsize);
04317    Int_t nbranches = fBranches.GetEntriesFast();
04318    for (Int_t i = 0; i < nbranches; ++i) {
04319       TBranch* branch = (TBranch*) fBranches[i];
04320       branch->SetBasketSize(fBasketSize);
04321    }
04322 }
04323 
04324 //______________________________________________________________________________
04325 void TBranchElement::SetBranchCount(TBranchElement* brOfCounter)
04326 {
04327    // -- Set the branch counter for this branch.
04328 
04329    fBranchCount = brOfCounter;
04330    if (fBranchCount==0) return;
04331 
04332    TLeafElement* leafOfCounter  = (TLeafElement*) brOfCounter->GetListOfLeaves()->At(0);
04333    TLeafElement* leaf = (TLeafElement*) GetListOfLeaves()->At(0);
04334    if (leafOfCounter && leaf) {
04335       leaf->SetLeafCount(leafOfCounter);
04336    } else {
04337       if (!leafOfCounter) {
04338          Warning("SetBranchCount", "Counter branch %s for branch %s has no leaves!", brOfCounter->GetName(), GetName());
04339       }
04340       if (!leaf) {
04341          Warning("SetBranchCount", "Branch %s has no leaves!", GetName());
04342       }
04343    }
04344 }
04345 
04346 //______________________________________________________________________________
04347 Bool_t TBranchElement::SetMakeClass(Bool_t decomposeObj)
04348 {
04349    // Set the branch in a mode where the object are decomposed
04350    // (Also known as MakeClass mode).
04351    // Return whether the setting was possible (it is not possible for
04352    // TBranch and TBranchObject).
04353 
04354    if (decomposeObj)
04355       SetBit(kDecomposedObj);   // Same as SetBit(kMakeClass)
04356    else
04357       ResetBit(kDecomposedObj);
04358       
04359    Int_t nbranches = fBranches.GetEntriesFast();
04360    for (Int_t i = 0; i < nbranches; ++i) {
04361       TBranchElement* branch = (TBranchElement*) fBranches[i];
04362       branch->SetMakeClass(decomposeObj);
04363    }
04364    SetReadLeavesPtr();
04365    
04366    return kTRUE;
04367 }
04368 
04369 //______________________________________________________________________________
04370 void TBranchElement::SetObject(void* obj)
04371 {
04372    // Set object this branch is pointing to.
04373 
04374    if (TestBit(kDoNotProcess)) {
04375       return;
04376    }
04377    fObject = (char*)obj;
04378    SetAddress( &fObject );
04379 }
04380 
04381 //______________________________________________________________________________
04382 void TBranchElement::SetOffset(Int_t offset)
04383 {
04384    // Set offset of the object (to which the data member represented by this
04385    // branch belongs) inside its containing object (if any).
04386    
04387    // We need to make sure that the Read and Write action's configuration
04388    // properly reflect this value.
04389    
04390    if (fReadActionSequence) {
04391       fReadActionSequence->AddToOffset(offset - fOffset);
04392    }
04393    fOffset = offset;
04394 }
04395    
04396 //______________________________________________________________________________
04397 void TBranchElement::SetReadActionSequence()
04398 {
04399    // Set the sequence of actions needed to read the data out of the buffer.
04400    
04401    if (fInfo == 0) {
04402       // We are called too soon.  We will be called again by InitInfo
04403       return;
04404    }
04405 
04406    // Get the action sequence we need to copy for reading.
04407    TStreamerInfoActions::TActionSequence *original = 0;
04408    TStreamerInfoActions::TActionSequence *transient = 0;
04409    if (fType == 41) {
04410       if( fSplitLevel >= TTree::kSplitCollectionOfPointers && fBranchCount->fSTLtype == TClassEdit::kVector) {
04411          original = fInfo->GetReadMemberWiseActions(kTRUE); 
04412       } else {
04413          TVirtualStreamerInfo *info = GetInfoImp();
04414          if (GetParentClass() == info->GetClass()) {
04415             if( fTargetClass.GetClassName()[0] && fBranchClass != fTargetClass ) {
04416                original = GetCollectionProxy()->GetConversionReadMemberWiseActions(fBranchClass.GetClass(), fClassVersion);
04417             } else {
04418                original = GetCollectionProxy()->GetReadMemberWiseActions(fClassVersion);
04419             }
04420          } else {
04421             // Base class and embedded objects.
04422             
04423             transient = TStreamerInfoActions::TActionSequence::CreateReadMemberWiseActions(info,*GetCollectionProxy());
04424             original = transient;
04425          }
04426       }
04427    } else if (fType == 31) {
04428       original = fInfo->GetReadMemberWiseActions(kTRUE);            
04429    } else if (0<=fType && fType<=2) {
04430       // Note: this still requires the ObjectWise sequence to not be optimized!
04431       original = fInfo->GetReadMemberWiseActions(kFALSE);
04432    }
04433    if (original) {
04434       fIDs.insert(fIDs.begin(),fID); // Include the main element in the sequence.
04435       if (fReadActionSequence) delete fReadActionSequence;
04436       fReadActionSequence = original->CreateSubSequence(fIDs,fOffset);
04437       fIDs.erase(fIDs.begin());
04438    }
04439    delete transient;
04440 }
04441 
04442 //______________________________________________________________________________
04443 void TBranchElement::SetReadLeavesPtr()
04444 {
04445    // Set the ReadLeaves pointer to execute the expected operations.
04446 
04447    if (TestBit(kDecomposedObj)) {
04448       fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesMakeClass;
04449    } else if (fType == 4) {
04450       fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesCollection;
04451    } else if (fType == 41) {
04452       if( fSplitLevel >= TTree::kSplitCollectionOfPointers ) {
04453          if (fBranchCount->fSTLtype == TClassEdit::kVector) {
04454             fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesCollectionSplitVectorPtrMember;
04455          } else {
04456             fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesCollectionSplitPtrMember;
04457          }
04458       } else {
04459          fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesCollectionMember;
04460       }
04461    } else if (fType == 3) {
04462       fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesClones;
04463    } else if (fType == 31) {
04464       fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesClonesMember;
04465    } else if (fType < 0) {
04466       fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesCustomStreamer;
04467    } else if (fType <=2) {
04468       // split-class branch, base class branch, data member branch, or top-level branch.
04469       if (fBranchCount) {
04470          fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesMemberBranchCount;         
04471       } else if (fStreamerType == TVirtualStreamerInfo::kCounter) {
04472          fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesMemberCounter;         
04473       } else {
04474          fReadLeaves = (ReadLeaves_t)&TBranchElement::ReadLeavesMember;
04475       }
04476    } else {
04477       Fatal("SetReadLeavePtr","Unexpected branch type %d for %s",fType,GetName());
04478    }
04479    
04480    SetReadActionSequence();
04481 }
04482 
04483 //______________________________________________________________________________
04484 void TBranchElement::SetTargetClass(const char *name)
04485 {
04486    // Set the name of the class of the in-memory object into which the data will
04487    // loaded.
04488 
04489    if (name == 0) return;
04490 
04491    if (strcmp(fTargetClass.GetClassName(),name) != 0 )
04492    {
04493       // We are changing target class, let's reset the meta information and
04494       // the sub-branches.
04495 
04496       fInfo = 0;
04497       fInit = kFALSE;
04498       fInitOffsets = kFALSE;
04499       delete fReadActionSequence;
04500       fReadActionSequence = 0;
04501 
04502       Int_t nbranches = fBranches.GetEntriesFast();
04503       for (Int_t i = 0; i < nbranches; ++i) {
04504          TBranchElement *sub = (TBranchElement*) fBranches[i];
04505          if (sub->fTargetClass == fTargetClass ) {
04506             sub->SetTargetClass(name);
04507          }
04508          if (sub->fParentClass == fTargetClass ) {
04509             sub->SetParentClass(TClass::GetClass(name));
04510          }
04511       }
04512       fTargetClass = name;
04513    }
04514 
04515 }
04516 
04517 //______________________________________________________________________________
04518 void TBranchElement::SetupAddresses()
04519 {
04520    // -- If the branch address is not set,  we set all addresses starting with
04521    // the top level parent branch.  This is required to be done in order for
04522    // GetOffset to be correct and for GetEntry to run.
04523 
04524    // Check to see if the user changed the branch address on us.
04525    ValidateAddress();
04526 
04527    if (fAddress || fTree->GetMakeClass()) {
04528       // -- Do nothing if already setup or if we are a MakeClass tree.
04529       return;
04530    }
04531 
04532    if (TestBit(kDoNotProcess|kAddressSet)) {
04533       // -- Do nothing if we have been told not to.
04534       // Or the data member in this branch is not longer part of the
04535       // parent's layout.
04536       return;
04537    }
04538 
04539    //--------------------------------------------------------------------------
04540    // Check if we are splited STL collection of pointers
04541    //--------------------------------------------------------------------------
04542    if( fType == 41 && fSplitLevel >= TTree::kSplitCollectionOfPointers )
04543    {
04544       TBranchElement *parent = (TBranchElement *)GetMother()->GetSubBranch( this );
04545 
04546       TVirtualStreamerInfo *sinfo = GetInfoImp();
04547       if (sinfo && sinfo->IsCompiled())
04548       {
04549          // If our streamer info has already been compiled,
04550          // then we must try to deal with schema evolution here.
04551          // FIXME: We must not optimize here or InitializeOffsets will crash!
04552          sinfo->BuildOld();
04553       }
04554 
04555       if( !parent->GetAddress() )
04556          parent->SetAddress( 0 );
04557       return;
04558    }
04559 
04560    //--------------------------------------------------------------------------
04561    // Any other case
04562    //--------------------------------------------------------------------------
04563    TBranchElement* mother = (TBranchElement*) GetMother();
04564    if (!mother) {
04565       return;
04566    }
04567    TClass* cl = TClass::GetClass(mother->GetClassName());
04568 
04569    {
04570       TVirtualStreamerInfo *sinfo = GetInfoImp();
04571       // FIXME: Should this go after the mother and cl test?
04572       if (sinfo && sinfo->IsCompiled()) {
04573          // If our streamer info has already been compiled,
04574          // then we must try to deal with schema evolution here.
04575          // FIXME: We must not optimize here or InitializeOffsets will crash!
04576          sinfo->BuildOld();
04577       }
04578    }
04579 
04580    if (!cl) {
04581       return;
04582    }
04583 
04584    if (!mother->GetAddress()) {
04585       // -- Our top-level branch has no address.
04586       Bool_t motherStatus = mother->TestBit(kDoNotProcess);
04587       mother->ResetBit(kDoNotProcess);
04588       // Note: This will allocate an object.
04589       mother->SetAddress(0);
04590       mother->SetBit(kDoNotProcess, motherStatus);
04591    }
04592 }
04593 
04594 //______________________________________________________________________________
04595 void TBranchElement::Streamer(TBuffer& R__b)
04596 {
04597    // -- Stream an object of class TBranchElement.
04598    if (R__b.IsReading()) {
04599       R__b.ReadClassBuffer(TBranchElement::Class(), this);
04600       fParentClass.SetName(fParentName);
04601       fBranchClass.SetName(fClassName);
04602       fTargetClass.SetName( fClassName );
04603       // The fAddress and fObject data members are not persistent,
04604       // therefore we do not own anything.
04605       // Also clear the bit possibly set by the schema evolution.
04606       ResetBit(kDeleteObject|kCache|kOwnOnfileObj|kAddressSet);
04607       // Fixup a case where the TLeafElement was missing
04608       if ((fType == 0) && (fLeaves.GetEntriesFast() == 0)) {
04609          TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
04610          leaf->SetTitle(GetTitle());
04611          fNleaves = 1;
04612          fLeaves.Add(leaf);
04613          fTree->GetListOfLeaves()->Add(leaf);
04614       }
04615       // SetReadLeavesPtr();
04616    }
04617    else {
04618       TDirectory* dirsav = fDirectory;
04619       fDirectory = 0;  // to avoid recursive calls
04620       {
04621          // Save class version.
04622          Int_t classVersion = fClassVersion;
04623          // Record only positive 'version number'
04624          if (fClassVersion < 0) {
04625             fClassVersion = -fClassVersion;
04626          }
04627          // TODO: Should we clear the kDeleteObject bit before writing?
04628          //       If we did we would have to remember the old value and
04629          //       put it back, we wouldn't want to forget that we owned
04630          //       something just because we got written to disk.
04631          R__b.WriteClassBuffer(TBranchElement::Class(), this);
04632          // Restore class version.
04633          fClassVersion = classVersion;
04634       }
04635       //
04636       //  Mark all streamer infos used by this branch element
04637       //  to be written to our output file.
04638       //
04639       {
04640          R__b.ForceWriteInfo(GetInfoImp(), kTRUE);
04641       }
04642       //
04643       //  If we are a clones array master branch, or an
04644       //  STL container master branch, we must also mark
04645       //  the streamer infos used by the value class to
04646       //  be written to our output file.
04647       //
04648       if (fType == 3) {
04649          // -- TClonesArray, counter/master branch
04650          //
04651          //  We must mark the streamer info for the
04652          //  value class to be written to the file.
04653          //
04654          const char* nm = GetClonesName();
04655          if (nm && strlen(nm)) {
04656             TClass* cl = TClass::GetClass(nm);
04657             if (cl) {
04658                R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
04659             }
04660          }
04661       }
04662       else if (fType == 4) {
04663          // -- STL container, counter/master branch
04664          //
04665          //  We must mark the streamer info for the
04666          //  value class to be written to the file.
04667          //
04668          TVirtualCollectionProxy* cp = GetCollectionProxy();
04669          if (cp) {
04670             TClass* cl = cp->GetValueClass();
04671             if (cl) {
04672                R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
04673             }
04674          }
04675       }
04676       // If we are in a separate file, then save
04677       // ourselves as an independent key.
04678       if (!dirsav) {
04679          // Note: No need to restore fDirectory, it was already zero.
04680          return;
04681       }
04682       if (!dirsav->IsWritable()) {
04683          fDirectory = dirsav;
04684          return;
04685       }
04686       TDirectory* pdirectory = fTree->GetDirectory();
04687       if (!pdirectory) {
04688          fDirectory = dirsav;
04689          return;
04690       }
04691       const char* treeFileName = pdirectory->GetFile()->GetName();
04692       TBranch* mother = GetMother();
04693       const char* motherFileName = treeFileName;
04694       if (mother && (mother != this)) {
04695          motherFileName = mother->GetFileName();
04696       }
04697       if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
04698          dirsav->WriteTObject(this);
04699       }
04700       fDirectory = dirsav;
04701    }
04702 }
04703 
04704 //______________________________________________________________________________
04705 Int_t TBranchElement::Unroll(const char* name, TClass* clParent, TClass* cl, char* ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
04706 {
04707    // -- Split class cl into sub-branches of this branch.
04708    //
04709    // Create a sub-branch of this branch for each non-empty,
04710    // non-abstract base class of cl (unless we are a sub-branch
04711    // of a TClonesArray or an STL container, in which case we
04712    // do *not* create a sub-branch), and for each non-split data
04713    // member of cl.
04714    //
04715    // Note: We do *not* create sub-branches for base classes of cl
04716    //       if we are a sub-branch of a TClonesArray or an STL container.
04717    //
04718    // Note: We do *not* create sub-branches for data members which
04719    //       have a class type and which we are splitting.
04720    //
04721    // Note: The above rules imply that the branch heirarchy increases
04722    //       in depth only for base classes of cl (unless we are inside
04723    //       of a TClonesArray or STL container, in which case the depth
04724    //       does *not* increase, the base class is elided) and for
04725    //       TClonesArray or STL container data members (which have one
04726    //       additional level of sub-branches).  The only other way the
04727    //       depth increases is when the top-level branch has a split
04728    //       class data member, in that case the constructor will create
04729    //       a sub-branch for it.  In other words, the interior nodes of
04730    //       the branch tree are all either: base class nodes; split
04731    //       class nodes which are direct sub-branches of top-level nodes
04732    //       (created by TClass::Bronch usually); or TClonesArray or STL
04733    //       container master nodes.
04734    //
04735    // Note: The exception to the above is for the top-level branches,
04736    //       Tree::Bronch creates nodes for everything in that case,
04737    //       except for a TObject base class of a class which has the
04738    //       can ignore tobject streamer flag set.
04739 
04740    //----------------------------------------------------------------------------
04741    // Handling the case of STL collections of pointers
04742    //----------------------------------------------------------------------------
04743    Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
04744    splitlevel %= TTree::kSplitCollectionOfPointers;
04745 
04746 
04747    TString branchname;
04748 
04749    if ((cl == TObject::Class()) && clParent->CanIgnoreTObjectStreamer()) {
04750       return 0;
04751    }
04752 
04753    //
04754    //  Rebuild the streamer info for cl unoptimized
04755    //  so that each data member has its own streamer
04756    //  element.  This allows each data member to have
04757    //  its own branch and thus be stored and queried
04758    //  independently in the tree.
04759    //
04760    TStreamerInfo* sinfo = fTree->BuildStreamerInfo(cl);
04761    if (splitlevel > 0) {
04762       sinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
04763       sinfo->Compile();
04764    }
04765 
04766    //
04767    //  Do nothing if we couldn't build the streamer info for cl.
04768    //
04769 
04770    if (!sinfo) {
04771       return 0;
04772    }
04773 
04774    Int_t ndata = sinfo->GetNdata();
04775    ULong_t* elems = sinfo->GetElems();
04776 
04777    if ((ndata == 1) && cl->GetCollectionProxy() && !strcmp(((TStreamerElement*) elems[0])->GetName(), "This")) {
04778       // -- Class cl is an STL collection, refuse to split it.
04779       // Question: Why?  We certainly could by switching to the value class.
04780       // Partial Answer: Only the branch element constructor can split STL containers.
04781       return 1;
04782    }
04783 
04784    for (Int_t elemID = 0; elemID < ndata; ++elemID) {
04785       // -- Loop over all the streamer elements and create sub-branches as needed.
04786       TStreamerElement* elem = (TStreamerElement*) elems[elemID];
04787       if (elem->IsA() == TStreamerArtificial::Class()) {
04788          continue;
04789       }
04790       if (elem->TestBit(TStreamerElement::kRepeat)) {
04791          continue;
04792       }
04793       Int_t offset = elem->GetOffset();
04794       // FIXME: An STL container as a base class gets TStreamerSTL as its class, so this test is not enough.
04795       // See InitializeOffsets() for the proper test.
04796       if (elem->IsA() == TStreamerBase::Class()) {
04797          // -- This is a base class of cl.
04798          TClass* clOfBase = TClass::GetClass(elem->GetName());
04799          if ((clOfBase->Property() & kIsAbstract) && cl->InheritsFrom(TCollection::Class())) {
04800             // -- Do nothing if we are abstract.
04801             // FIXME: We should not test for TCollection here.
04802             return -1;
04803          }
04804          if ((btype == 31) || (btype == 41)) {
04805             // -- Elide the base-class sub-branches of a split TClonesArray or STL container.
04806             //
04807             // Note: We are eliding the base class here, that is, we never
04808             //       create a branch for it, so the branch heirarchy is not
04809             //       complete.
04810             // Note: The clParent parameter is the value class of the
04811             //       container which we are splitting.  It does not
04812             //       appear in the branch heirarchy either.
04813             // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
04814             Int_t unroll = Unroll(name, clParent, clOfBase, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
04815             if (unroll < 0) {
04816                // FIXME: We could not split because we are abstract, should we be doing this?
04817                if (strlen(name)) {
04818                   branchname.Form("%s.%s", name, elem->GetFullName());
04819                } else {
04820                   branchname.Form("%s", elem->GetFullName());
04821                }
04822                TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, 0, btype);
04823                branch->SetParentClass(clParent);
04824                fBranches.Add(branch);
04825             }
04826          } else if (clOfBase->GetListOfRealData()->GetSize()) {
04827             // -- Create a branch for a non-empty base class.
04828             if (strlen(name)) {
04829                branchname.Form("%s.%s", name, elem->GetFullName());
04830                // Elide the base class name when creating the sub-branches.
04831                // Note: The branch names for sub-branches of a base class branch
04832                //       do not represent the full class heirarchy because we do
04833                //       this, however it does keep the branch names for the
04834                //       inherited data members simple.
04835                TBranchElement* branch = new TBranchElement(this, name, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
04836                // Then reset it to the proper name.
04837                branch->SetName(branchname);
04838                branch->SetTitle(branchname);
04839                branch->SetParentClass(clParent);
04840                fBranches.Add(branch);
04841             } else {
04842                branchname.Form("%s", elem->GetFullName());
04843                TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
04844                branch->SetParentClass(clParent);
04845                fBranches.Add(branch);
04846             }
04847          }
04848       } else {
04849          // -- This is a data member of cl.
04850          if (strlen(name)) {
04851             branchname.Form("%s.%s", name, elem->GetFullName());
04852          } else {
04853             branchname.Form("%s", elem->GetFullName());
04854          }
04855          if ((splitlevel > 1) && ((elem->IsA() == TStreamerObject::Class()) || (elem->IsA() == TStreamerObjectAny::Class()))) {
04856             // -- We are splitting a non-TClonesArray (may inherit from TClonesArray though), non-STL container object.
04857             //
04858             // Ignore an abstract class.
04859             // FIXME: How could an abstract class get here?
04860             //        Partial answer: It is a base class.  But this is a data member!
04861             TClass* elemClass = TClass::GetClass(elem->GetTypeName());
04862             if (elemClass->Property() & kIsAbstract) {
04863                return -1;
04864             }
04865             if (elem->CannotSplit()) {
04866                // We are not splitting.
04867                TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
04868                branch->SetParentClass(clParent);
04869                fBranches.Add(branch);
04870             } else if (elemClass->InheritsFrom(TClonesArray::Class())) {
04871                // Splitting something derived from TClonesArray.
04872                Int_t subSplitlevel = splitlevel-1;
04873                if (btype == 31 || btype == 41 || elem->CannotSplit()) {
04874                   // -- We split the sub-branches of a TClonesArray or an STL container only once.
04875                   subSplitlevel = 0;
04876                }
04877                TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel, btype);
04878                branch->SetParentClass(clParent);
04879                fBranches.Add(branch);
04880             } else {
04881                // Splitting a normal class.
04882                // FIXME: We are eliding the class we are splitting here,
04883                //        i.e., we do not create a branch for it, so the
04884                //        branch heirarchy does not match the class heirarchy.
04885                // Note: clParent is the class which contains a data member of
04886                //       the class type which we are splitting.
04887                // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
04888                Int_t unroll = Unroll(branchname, clParent, elemClass, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
04889                if (unroll < 0) {
04890                   // FIXME: We could not split because we are abstract, should we be doing this?
04891                   TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
04892                   branch->SetParentClass(clParent);
04893                   fBranches.Add(branch);
04894                }
04895             }
04896          }
04897          else if( elem->GetClassPointer() &&
04898                   elem->GetClassPointer()->GetCollectionProxy() &&
04899                   elem->GetClassPointer()->GetCollectionProxy()->HasPointers() &&
04900                   splitSTLP && fType != 4 )
04901          {
04902 
04903             TBranchSTL* branch = new TBranchSTL( this, branchname,
04904                                                  elem->GetClassPointer()->GetCollectionProxy(),
04905                                                  basketsize, splitlevel - 1+splitSTLP, sinfo, elemID );
04906             branch->SetAddress( ptr+offset );
04907             fBranches.Add( branch );
04908          }
04909          else if ((elem->IsA() == TStreamerSTL::Class()) && !elem->IsaPointer()) {
04910             // -- We have an STL container.
04911             // Question: What if splitlevel == 0 here?
04912             // Answer: then we should not be here.
04913             Int_t subSplitlevel = splitlevel - 1;
04914             if ((btype == 31) || (btype == 41) || elem->CannotSplit()) {
04915                // -- We split the sub-branches of a TClonesArray or an STL container only once.
04916                subSplitlevel = 0;
04917             }
04918             TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel+splitSTLP, btype);
04919             branch->SetParentClass(clParent);
04920             fBranches.Add(branch);
04921          } else if (((btype != 31) && (btype != 41)) && ptr && ((elem->GetClassPointer() == TClonesArray::Class()) || ((elem->IsA() == TStreamerSTL::Class()) && !elem->CannotSplit()))) {
04922             // -- We have a TClonesArray.
04923             // FIXME: We could get a ptr to a TClonesArray here by mistake.
04924             // Question: What if splitlevel == 0 here?
04925             // Answer: then we should not be here.
04926             // Note: ptr may be null in case of a TClonesArray inside another
04927             //       TClonesArray or STL container, see the else clause.
04928             TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
04929             branch->SetParentClass(clParent);
04930             fBranches.Add(branch);
04931          } else {
04932             // -- We are not going to split this element any farther.
04933             TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, splitSTLP, btype);
04934             branch->SetType(btype);
04935             branch->SetParentClass(clParent);
04936             fBranches.Add(branch);
04937          }
04938       }
04939    }
04940 
04941    return 1;
04942 }
04943 
04944 //______________________________________________________________________________
04945 void TBranchElement::UpdateFile()
04946 {
04947    // Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
04948    // with the current value of fTree->GetCurrentFile unless this branch has been
04949    // redirected to a different file.  Also update the sub-branches.
04950 
04951    // The BranchCount and BranchCount2 are part of higher level branches' list of
04952    // branches.
04953    // if (fBranchCount) fBranchCount->UpdateFile();
04954    // if (fBranchCount2) fBranchCount2->UpdateFile();
04955    TBranch::UpdateFile();
04956 }

Generated on Tue Jul 5 15:33:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1