TBranchObject.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TBranchObject.cxx 38060 2011-02-13 21:17:54Z pcanal $
00002 // Author: Rene Brun   11/02/96
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 // TBranchObject                                                        //
00015 //                                                                      //
00016 // A Branch for the case of an object                                   //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 
00020 #include "TBranchObject.h"
00021 
00022 #include "TBasket.h"
00023 #include "TBranchClones.h"
00024 #include "TBrowser.h"
00025 #include "TClass.h"
00026 #include "TClonesArray.h"
00027 #include "TDataMember.h"
00028 #include "TDataType.h"
00029 #include "TFile.h"
00030 #include "TLeafObject.h"
00031 #include "TRealData.h"
00032 #include "TStreamerInfo.h"
00033 #include "TTree.h"
00034 #include "TVirtualPad.h"
00035 
00036 ClassImp(TBranchObject)
00037 
00038 //______________________________________________________________________________
00039 TBranchObject::TBranchObject()
00040 : TBranch()
00041 {
00042    // Default constructor for BranchObject.
00043 
00044    fNleaves = 1;
00045    fOldObject = 0;
00046 }
00047 
00048 //______________________________________________________________________________
00049 TBranchObject::TBranchObject(TTree *tree, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t splitlevel, Int_t compress, Bool_t isptrptr /* = kTRUE */)
00050 : TBranch()
00051 {
00052    // Create a BranchObject.
00053 
00054    Init(tree,0,name,classname,addobj,basketsize,splitlevel,compress,isptrptr);
00055 }
00056 
00057 //______________________________________________________________________________
00058 TBranchObject::TBranchObject(TBranch *parent, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t splitlevel, Int_t compress, Bool_t isptrptr /* = kTRUE */)
00059 : TBranch()
00060 {
00061    // Create a BranchObject.
00062 
00063    Init(0,parent,name,classname,addobj,basketsize,splitlevel,compress,isptrptr);
00064 }
00065 
00066 //______________________________________________________________________________
00067 void TBranchObject::Init(TTree *tree, TBranch *parent, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t /*splitlevel*/, Int_t compress, Bool_t isptrptr)
00068 {
00069    // Initialization routine (run from the constructor so do not make this function virtual)
00070 
00071    if (tree==0 && parent!=0) tree = parent->GetTree();
00072    fTree   = tree;
00073    fMother = parent ? parent->GetMother() : this;
00074    fParent = parent;
00075 
00076    TClass* cl = TClass::GetClass(classname);
00077 
00078    if (!cl) {
00079       Error("TBranchObject", "Cannot find class:%s", classname);
00080       return;
00081    }
00082 
00083    if (!isptrptr) {
00084       fOldObject = (TObject*)addobj;
00085       addobj = &fOldObject;
00086    }
00087 
00088    char** apointer = (char**) addobj;
00089    TObject* obj = (TObject*) (*apointer);
00090 
00091    Bool_t delobj = kFALSE;
00092    if (!obj) {
00093       obj = (TObject*) cl->New();
00094       delobj = kTRUE;
00095    }
00096 
00097    tree->BuildStreamerInfo(cl, obj);
00098 
00099    if (delobj) {
00100       cl->Destructor(obj);
00101    }
00102 
00103    SetName(name);
00104    SetTitle(name);
00105 
00106    fCompress = compress;
00107    if ((compress == -1) && tree->GetDirectory()) {
00108       TFile* bfile = tree->GetDirectory()->GetFile();
00109       if (bfile) {
00110          fCompress = bfile->GetCompressionLevel();
00111       }
00112    }
00113    if (basketsize < 100) {
00114       basketsize = 100;
00115    }
00116    fBasketSize = basketsize;
00117    fAddress = (char*) addobj;
00118    fClassName = classname;
00119    fBasketBytes = new Int_t[fMaxBaskets];
00120    fBasketEntry = new Long64_t[fMaxBaskets];
00121    fBasketSeek = new Long64_t[fMaxBaskets];
00122    fOldObject = 0;
00123 
00124    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00125       fBasketBytes[i] = 0;
00126       fBasketEntry[i] = 0;
00127       fBasketSeek[i] = 0;
00128    }
00129 
00130    TLeaf* leaf = new TLeafObject(this, name, classname);
00131    leaf->SetAddress(addobj);
00132    fNleaves = 1;
00133    fLeaves.Add(leaf);
00134    tree->GetListOfLeaves()->Add(leaf);
00135 
00136    // Set the bit kAutoDelete to specify that when reading
00137    // in TLeafObject::ReadBasket, the object should be deleted
00138    // before calling Streamer.
00139    // It is foreseen to not set this bit in a future version.
00140    SetAutoDelete(kTRUE);
00141 
00142    fDirectory = fTree->GetDirectory();
00143    fFileName = "";
00144 
00145 }
00146 
00147 //______________________________________________________________________________
00148 TBranchObject::~TBranchObject()
00149 {
00150    // Destructor for a BranchObject.
00151    fBranches.Delete();
00152 }
00153 
00154 //______________________________________________________________________________
00155 void TBranchObject::Browse(TBrowser* b)
00156 {
00157    // Browse the branch content.
00158 
00159    Int_t nbranches = fBranches.GetEntriesFast();
00160    if (nbranches > 1) {
00161       fBranches.Browse(b);
00162    }
00163    if (GetBrowsables() && GetBrowsables()->GetSize()) {
00164       GetBrowsables()->Browse(b);
00165    }
00166 }
00167 
00168 //______________________________________________________________________________
00169 Int_t TBranchObject::Fill()
00170 {
00171    // Loop on all leaves of this branch to fill Basket buffer.
00172 
00173    Int_t nbytes = 0;
00174    Int_t nbranches = fBranches.GetEntriesFast();
00175    if (nbranches) {
00176       ++fEntries;
00177       UpdateAddress();
00178       for (Int_t i = 0; i < nbranches; ++i)  {
00179          TBranch* branch = (TBranch*) fBranches[i];
00180          if (!branch->TestBit(kDoNotProcess)) {
00181             Int_t bc = branch->Fill();
00182             nbytes += bc;
00183          }
00184       }
00185    } else {
00186       if (!TestBit(kDoNotProcess)) {
00187          Int_t bc = TBranch::Fill();
00188          nbytes += bc;
00189       }
00190    }
00191    return nbytes;
00192 }
00193 
00194 //______________________________________________________________________________
00195 Int_t TBranchObject::GetEntry(Long64_t entry, Int_t getall)
00196 {
00197    // Read all branches of a BranchObject and return total number of bytes.
00198    //
00199    //   If entry = 0 take current entry number + 1
00200    //   If entry < 0 reset entry number to 0
00201    //
00202    //  The function returns the number of bytes read from the input buffer.
00203    //  If entry does not exist  the function returns 0.
00204    //  If an I/O error occurs,  the function returns -1.
00205 
00206    if (TestBit(kDoNotProcess) && !getall) {
00207       return 0;
00208    }
00209    Int_t nbytes;
00210    Int_t nbranches = fBranches.GetEntriesFast();
00211 
00212    if (nbranches) {
00213       if (fAddress == 0) {
00214          SetupAddresses();
00215       }
00216       nbytes = 0;
00217       Int_t nb;
00218       for (Int_t i = 0; i < nbranches; ++i)  {
00219          TBranch* branch = (TBranch*) fBranches[i];
00220          if (branch) {
00221             nb = branch->GetEntry(entry, getall);
00222             if (nb < 0) {
00223                return nb;
00224             }
00225             nbytes += nb;
00226          }
00227       }
00228    } else {
00229       nbytes = TBranch::GetEntry(entry, getall);
00230    }
00231    return nbytes;
00232 }
00233 
00234 //______________________________________________________________________________
00235 Int_t TBranchObject::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
00236 {
00237    // Fill expectedClass and expectedType with information on the data type of the 
00238    // object/values contained in this branch (and thus the type of pointers
00239    // expected to be passed to Set[Branch]Address
00240    // return 0 in case of success and > 0 in case of failure.
00241    
00242    expectedClass = 0;
00243    expectedType = kOther_t;
00244    TLeafObject* lobj = (TLeafObject*) GetListOfLeaves()->At(0);
00245    if (!lobj) {
00246       Error("GetExpectedType", "Did not find any leaves in %s",GetName());
00247       return 1;
00248    }
00249    expectedClass = lobj->GetClass();
00250    return 0;
00251 }
00252 
00253 //______________________________________________________________________________
00254 Bool_t TBranchObject::IsFolder() const
00255 {
00256    // Return TRUE if more than one leaf or if fBrowsables, FALSE otherwise.
00257 
00258    Int_t nbranches = fBranches.GetEntriesFast();
00259 
00260    if (nbranches >= 1) {
00261       return kTRUE;
00262    }
00263 
00264    TList* browsables = const_cast<TBranchObject*>(this)->GetBrowsables();
00265 
00266    return browsables && browsables->GetSize();
00267 }
00268 
00269 //______________________________________________________________________________
00270 void TBranchObject::Print(Option_t* option) const
00271 {
00272    // Print TBranch parameters.
00273 
00274    Int_t nbranches = fBranches.GetEntriesFast();
00275    if (nbranches) {
00276       Printf("*Branch  :%-9s : %-54s *", GetName(), GetTitle());
00277       Printf("*Entries : %8d : BranchObject (see below)                               *", Int_t(fEntries));
00278       Printf("*............................................................................*");
00279       for (Int_t i = 0; i < nbranches; ++i)  {
00280          TBranch* branch = (TBranch*) fBranches.At(i);
00281          if (branch) {
00282             branch->Print(option);
00283          }
00284       }
00285    } else {
00286       TBranch::Print(option);
00287    }
00288 }
00289 
00290 //______________________________________________________________________________
00291 void TBranchObject::Reset(Option_t* option)
00292 {
00293    // Reset a branch.
00294    //
00295    // Existing buffers are deleted.
00296    // Entries, max and min are reset.
00297 
00298    TBranch::Reset(option);
00299 
00300    Int_t nbranches = fBranches.GetEntriesFast();
00301    for (Int_t i = 0; i < nbranches; ++i)  {
00302       TBranch* branch = (TBranch*) fBranches[i];
00303       branch->Reset(option);
00304    }
00305 }
00306 
00307 //______________________________________________________________________________
00308 void TBranchObject::SetAddress(void* add)
00309 {
00310    // Set address of this branch.
00311 
00312    if (TestBit(kDoNotProcess)) {
00313       return;
00314    }
00315 
00316    // Special case when called from code generated by TTree::MakeClass.
00317    if (Long_t(add) == -1) {
00318       SetBit(kWarn);
00319       return;
00320    }
00321 
00322    fReadEntry = -1;
00323    Int_t nbranches = fBranches.GetEntriesFast();
00324 
00325    TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
00326    if (leaf) {
00327       leaf->SetAddress(add);
00328    }
00329 
00330    fAddress = (char*) add;
00331    char** ppointer = (char**) add;
00332 
00333    char* obj = 0;
00334    if (ppointer) {
00335       obj = *ppointer;
00336    }
00337 
00338    TClass* cl = TClass::GetClass(fClassName.Data());
00339 
00340    if (!cl) {
00341       for (Int_t i = 0; i < nbranches; ++i)  {
00342          TBranch* br = (TBranch*) fBranches[i];
00343          br->SetAddress(obj);
00344       }
00345       return;
00346    }
00347 
00348    if (ppointer && !obj) {
00349       obj = (char*) cl->New();
00350       *ppointer = obj;
00351    }
00352 
00353    if (!cl->GetListOfRealData()) {
00354       cl->BuildRealData(obj);
00355    }
00356 
00357    if (cl->InheritsFrom(TClonesArray::Class())) {
00358       if (ppointer) {
00359          TClonesArray* clones = (TClonesArray*) *ppointer;
00360          if (!clones) {
00361             Error("SetAddress", "Pointer to TClonesArray is null");
00362             return;
00363          }
00364          TClass* clm = clones->GetClass();
00365          if (clm) {
00366             clm->BuildRealData(); //just in case clm derives from an abstract class
00367             clm->GetStreamerInfo();
00368          }
00369       }
00370    }
00371 
00372    //
00373    // Loop over our data members looking
00374    // for sub-branches for them.  If we
00375    // find one, set its address.
00376    //
00377 
00378    char* fullname = new char[200];
00379 
00380    const char* bname = GetName();
00381 
00382    Int_t isDot = 0;
00383    if (bname[strlen(bname)-1] == '.') {
00384       isDot = 1;
00385    }
00386 
00387    char* pointer = 0;
00388    TRealData* rd = 0;
00389    TIter next(cl->GetListOfRealData());
00390    while ((rd = (TRealData*) next())) {
00391       if (rd->TestBit(TRealData::kTransient)) continue;
00392 
00393       TDataMember* dm = rd->GetDataMember();
00394       if (!dm || !dm->IsPersistent()) {
00395          continue;
00396       }
00397       const char* rdname = rd->GetName();
00398       TDataType* dtype = dm->GetDataType();
00399       Int_t code = 0;
00400       if (dtype) {
00401          code = dm->GetDataType()->GetType();
00402       }
00403       Int_t offset = rd->GetThisOffset();
00404       if (ppointer) {
00405          pointer = obj + offset;
00406       }
00407       TBranch* branch = 0;
00408       if (dm->IsaPointer()) {
00409          TClass* clobj = 0;
00410          if (!dm->IsBasic()) {
00411             clobj = TClass::GetClass(dm->GetTypeName());
00412          }
00413          if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
00414             if (isDot) {
00415                snprintf(fullname,200, "%s%s", bname, &rdname[1]);
00416             } else {
00417                snprintf(fullname,200, "%s", &rdname[1]);
00418             }
00419             branch = (TBranch*) fBranches.FindObject(fullname);
00420          } else {
00421             if (!clobj) {
00422                // this is a basic type we can handle only if
00423                // he has a dimension:
00424                const char* index = dm->GetArrayIndex();
00425                if (strlen(index) == 0) {
00426                   if (code == 1) {
00427                      // Case of a string ... we do not need the size
00428                      if (isDot) {
00429                         snprintf(fullname,200, "%s%s", bname, &rdname[0]);
00430                      } else {
00431                         snprintf(fullname,200, "%s", &rdname[0]);
00432                      }
00433                   } else {
00434                      continue;
00435                   }
00436                }
00437                if (isDot) {
00438                   snprintf(fullname,200, "%s%s", bname, &rdname[0]);
00439                } else {
00440                   snprintf(fullname,200, "%s", &rdname[0]);
00441                }
00442                // let's remove the stars!
00443                UInt_t cursor;
00444                UInt_t pos;
00445                for (cursor = 0, pos = 0; cursor < strlen(fullname); ++cursor) {
00446                   if (fullname[cursor] != '*') {
00447                      fullname[pos++] = fullname[cursor];
00448                   }
00449                }
00450                fullname[pos] = '\0';
00451                branch = (TBranch*) fBranches.FindObject(fullname);
00452             } else {
00453                if (!clobj->InheritsFrom(TObject::Class())) {
00454                   continue;
00455                }
00456                if (isDot) {
00457                   snprintf(fullname,200, "%s%s", bname, &rdname[1]);
00458                } else {
00459                   snprintf(fullname,200, "%s", &rdname[1]);
00460                }
00461                branch = (TBranch*) fBranches.FindObject(fullname);
00462             }
00463          }
00464       } else {
00465          if (dm->IsBasic()) {
00466             if (isDot) {
00467                snprintf(fullname,200, "%s%s", bname, &rdname[0]);
00468             } else {
00469                snprintf(fullname,200, "%s", &rdname[0]);
00470             }
00471             branch = (TBranch*) fBranches.FindObject(fullname);
00472          }
00473       }
00474       if (branch) {
00475          branch->SetAddress(pointer);
00476       }
00477    }
00478 
00479    delete[] fullname;
00480 }
00481 
00482 //______________________________________________________________________________
00483 void TBranchObject::SetAutoDelete(Bool_t autodel)
00484 {
00485    // Set the AutoDelete bit.
00486    //
00487    //  This function can be used to instruct Root in TBranchObject::ReadBasket
00488    //  to not delete the object referenced by a branchobject before reading a
00489    //  new entry. By default, the object is deleted.
00490    //  If autodel is kTRUE, this existing object will be deleted, a new object
00491    //    created by the default constructor, then object->Streamer called.
00492    //  If autodel is kFALSE, the existing object is not deleted. Root assumes
00493    //    that the user is taking care of deleting any internal object or array
00494    //    This can be done in Streamer itself.
00495    //  If this branch has sub-branches, the function sets autodel for these
00496    //  branches as well.
00497    //  We STRONGLY suggest to activate this option by default when you create
00498    //  the top level branch. This will make the read phase more efficient
00499    //  because it minimizes the numbers of new/delete operations.
00500    //  Once this option has been set and the Tree is written to a file, it is
00501    //  not necessary to specify the option again when reading, unless you
00502    //  want to set the opposite mode.
00503    //
00504 
00505    TBranch::SetAutoDelete(autodel);
00506 
00507    Int_t nbranches = fBranches.GetEntriesFast();
00508    for (Int_t i=0;i<nbranches;i++)  {
00509       TBranch *branch = (TBranch*)fBranches[i];
00510       branch->SetAutoDelete(autodel);
00511    }
00512 }
00513 
00514 //______________________________________________________________________________
00515 void TBranchObject::SetBasketSize(Int_t buffsize)
00516 {
00517    // Reset basket size for all subbranches of this branch.
00518 
00519    TBranch::SetBasketSize(buffsize);
00520 
00521    Int_t nbranches = fBranches.GetEntriesFast();
00522    for (Int_t i = 0; i < nbranches; ++i)  {
00523       TBranch* branch = (TBranch*) fBranches[i];
00524       branch->SetBasketSize(fBasketSize);
00525    }
00526 }
00527 
00528 //______________________________________________________________________________
00529 void TBranchObject::Streamer(TBuffer& R__b)
00530 {
00531    // Stream an object of class TBranchObject.
00532 
00533    if (R__b.IsReading()) {
00534       R__b.ReadClassBuffer(TBranchObject::Class(), this);
00535    } else {
00536       TDirectory* dirsav = fDirectory;
00537       fDirectory = 0;  // to avoid recursive calls
00538 
00539       R__b.WriteClassBuffer(TBranchObject::Class(), this);
00540 
00541       // make sure that all TStreamerInfo objects referenced by
00542       // this class are written to the file
00543       R__b.ForceWriteInfo(TClass::GetClass(fClassName.Data())->GetStreamerInfo(), kTRUE);
00544 
00545       // if branch is in a separate file save this branch
00546       // as an independent key
00547       if (!dirsav) {
00548          return;
00549       }
00550       if (!dirsav->IsWritable()) {
00551          fDirectory = dirsav;
00552          return;
00553       }
00554       TDirectory* pdirectory = fTree->GetDirectory();
00555       if (!pdirectory) {
00556          fDirectory = dirsav;
00557          return;
00558       }
00559       const char* treeFileName = pdirectory->GetFile()->GetName();
00560       TBranch* mother = GetMother();
00561       const char* motherFileName = treeFileName;
00562       if (mother && (mother != this)) {
00563          motherFileName = mother->GetFileName();
00564       }
00565       if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
00566          dirsav->WriteTObject(this);
00567       }
00568       fDirectory = dirsav;
00569    }
00570 }
00571 
00572 //______________________________________________________________________________
00573 void TBranchObject::SetupAddresses()
00574 {
00575    // -- If the branch address is not set,  we set all addresses starting with
00576    // the top level parent branch.  This is required to be done in order for
00577    // GetOffset to be correct and for GetEntry to run.
00578  
00579    if (fAddress == 0) {
00580       // try to create object
00581       if (!TestBit(kWarn)) {
00582          TClass* cl = TClass::GetClass(fClassName);
00583          if (cl) {
00584             TObject** voidobj = (TObject**) new Long_t[1];
00585             *voidobj = (TObject*) cl->New();
00586             SetAddress(voidobj);
00587          } else {
00588             Warning("GetEntry", "Cannot get class: %s", fClassName.Data());
00589             SetBit(kWarn);
00590          }
00591       }
00592    }   
00593 }
00594 
00595 //______________________________________________________________________________
00596 void TBranchObject::UpdateAddress()
00597 {
00598    // Update branch addresses if a new object was created.
00599 
00600    void** ppointer = (void**) fAddress;
00601    if (!ppointer) {
00602       return;
00603    }
00604    TObject* obj = (TObject*) (*ppointer);
00605    if (obj != fOldObject) {
00606       fOldObject = obj;
00607       SetAddress(fAddress);
00608    }
00609 }
00610 

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