Logo ROOT   6.07/09
Reference Guide
TBranchElement.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Authors Rene Brun , Philippe Canal, Markus Frank 14/01/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TBranchElement
13 \ingroup tree
14 
15 A Branch for the case of an object.
16 */
17 
18 #include "TBranchElement.h"
19 
20 #include "TBasket.h"
21 #include "TBranchObject.h"
22 #include "TBranchRef.h"
23 #include "TBrowser.h"
24 #include "TClass.h"
25 #include "TClassEdit.h"
26 #include "TClonesArray.h"
27 #include "TDataMember.h"
28 #include "TDataType.h"
29 #include "TError.h"
30 #include "TMath.h"
31 #include "TFile.h"
32 #include "TFolder.h"
33 #include "TLeafElement.h"
34 #include "TRealData.h"
35 #include "TStreamerElement.h"
36 #include "TStreamerInfo.h"
37 #include "TTree.h"
40 #include "TVirtualMutex.h"
41 #include "TVirtualPad.h"
42 #include "TBranchSTL.h"
43 #include "TVirtualArray.h"
44 #include "TBufferFile.h"
45 #include "TInterpreter.h"
46 #include "TROOT.h"
47 
48 #include "TStreamerInfoActions.h"
49 #include "TSchemaRuleSet.h"
50 
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 
55 namespace {
56  void RemovePrefix(TString& str, const char* prefix) {
57  // -- Remove a prefix from a string.
58  if (str.Length() && prefix && strlen(prefix)) {
59  if (!str.Index(prefix)) {
60  str.Remove(0, strlen(prefix));
61  }
62  }
63  }
64  struct R__PushCache {
65  TBufferFile &fBuffer;
66  TVirtualArray *fOnfileObject;
67 
68  R__PushCache(TBufferFile &b, TVirtualArray *in, UInt_t size) : fBuffer(b), fOnfileObject(in) {
69  if (fOnfileObject) {
70  fOnfileObject->SetSize(size);
71  fBuffer.PushDataCache( fOnfileObject );
72  }
73  }
74  ~R__PushCache() {
75  if (fOnfileObject) fBuffer.PopDataCache();
76  }
77  };
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// Modify the container type of the branches
82 
84  const Int_t nbranches = branches->GetEntriesFast();
85  for (Int_t i = 0; i < nbranches; ++i) {
86  TBranchElement* br = (TBranchElement*) branches->At(i);
87  switch (br->GetType()) {
88  case 31: br->SetType(41); break;
89  case 41: {
90  br->SetType(31);
91  br->fCollProxy = 0;
92  break;
93  }
94  }
95  br->SetReadLeavesPtr();
96  br->SetFillLeavesPtr();
97  // Note: This is a tail recursion.
98  SwitchContainer(br->GetListOfBranches());
99  }
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 
104 namespace {
105  Bool_t CanSelfReference(TClass *cl) {
106  if (cl) {
107  if (cl->GetCollectionProxy()) {
108  TClass *inside = cl->GetCollectionProxy()->GetValueClass();
109  if (inside) {
110  return CanSelfReference(inside);
111  } else {
112  return kFALSE;
113  }
114  }
115  const static TClassRef stringClass("std::string");
116  if (cl == stringClass || cl == TString::Class()) {
117  return kFALSE;
118  }
119  // Here we could scan through the TStreamerInfo to see if there
120  // is any pointer anywhere and know whether this is a possibility
121  // of selfreference (but watch out for very indirect cases).
122  return kTRUE;
123  }
124  return kFALSE;
125  }
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Default and I/O constructor.
130 
132 : TBranch()
133 , fClassName()
134 , fParentName()
135 , fClonesName()
136 , fCollProxy(0)
137 , fCheckSum(0)
138 , fClassVersion(0)
139 , fID(0)
140 , fType(0)
141 , fStreamerType(-1)
142 , fMaximum(0)
143 , fSTLtype(ROOT::kNotSTL)
144 , fNdata(1)
145 , fBranchCount(0)
146 , fBranchCount2(0)
147 , fInfo(0)
148 , fObject(0)
149 , fOnfileObject(0)
150 , fInit(kFALSE)
151 , fInitOffsets(kFALSE)
152 , fTargetClass()
153 , fCurrentClass()
154 , fParentClass()
155 , fBranchClass()
156 , fClonesClass()
157 , fBranchOffset(0)
158 , fBranchID(-1)
159 , fReadActionSequence(0)
160 , fFillActionSequence(0)
161 , fIterators(0)
162 , fWriteIterators(0)
163 , fPtrIterators(0)
164 {
165  fNleaves = 0;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Constructor when the branch object is not a TClonesArray nor an STL container.
172 ///
173 /// If splitlevel > 0 this branch in turn is split into sub-branches.
174 
175 TBranchElement::TBranchElement(TTree *tree, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
176 : TBranch()
177 , fClassName(sinfo->GetName())
178 , fParentName()
179 , fClonesName()
180 , fCollProxy(0)
181 , fCheckSum(sinfo->GetCheckSum())
183 , fID(id)
184 , fType(0)
185 , fStreamerType(-1)
186 , fMaximum(0)
188 , fNdata(1)
189 , fBranchCount(0)
190 , fBranchCount2(0)
191 , fInfo(sinfo)
192 , fObject(0)
193 , fOnfileObject(0)
194 , fInit(kTRUE)
197 , fCurrentClass()
198 , fParentClass()
199 , fBranchClass(sinfo->GetClass())
200 , fClonesClass()
201 , fBranchOffset(0)
202 , fBranchID(-1)
205 , fIterators(0)
206 , fWriteIterators(0)
207 , fPtrIterators(0)
208 {
209  Init(tree, 0, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Constructor when the branch object is not a TClonesArray nor an STL container.
214 ///
215 /// If splitlevel > 0 this branch in turn is split into sub-branches.
216 
217 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
218 : TBranch()
219 , fClassName(sinfo->GetName())
220 , fParentName()
221 , fClonesName()
222 , fCollProxy(0)
223 , fCheckSum(sinfo->GetCheckSum())
225 , fID(id)
226 , fType(0)
227 , fStreamerType(-1)
228 , fMaximum(0)
230 , fNdata(1)
231 , fBranchCount(0)
232 , fBranchCount2(0)
233 , fInfo(sinfo)
234 , fObject(0)
235 , fOnfileObject(0)
236 , fInit(kTRUE)
239 , fCurrentClass()
240 , fParentClass()
241 , fBranchClass(sinfo->GetClass())
242 , fClonesClass()
243 , fBranchOffset(0)
244 , fBranchID(-1)
247 , fIterators(0)
248 , fWriteIterators(0)
249 , fPtrIterators(0)
250 {
251  Init(parent ? parent->GetTree() : 0, parent, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Init when the branch object is not a TClonesArray nor an STL container.
256 ///
257 /// If splitlevel > 0 this branch in turn is split into sub-branches.
258 
259 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)
260 {
261  TString name(bname);
262 
263  // Set our TNamed attributes.
264  SetName(name);
265  SetTitle(name);
266 
267  // Set our TBranch attributes.
268  fSplitLevel = splitlevel;
269  fTree = tree;
270  if (fTree == 0) return;
271  fMother = parent ? parent->GetMother() : this;
272  fParent = parent;
274  fFileName = "";
275 
276  // Clear the bit kAutoDelete to specify that when reading
277  // the object should not be deleted before calling Streamer.
278 
280 
283 
284  //---------------------------------------------------------------------------
285  // Handling the splitting of the STL collections of pointers
286  /////////////////////////////////////////////////////////////////////////////
287 
288  Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
289  splitlevel %= TTree::kSplitCollectionOfPointers;
290 
291  fCompress = -1;
292  if (fTree->GetDirectory()) {
293  TFile* bfile = fTree->GetDirectory()->GetFile();
294  if (bfile) {
296  }
297  }
298 
299  //
300  // Initialize streamer type and element.
301  //
302 
303  if (id > -1) {
304  // We are *not* a top-level branch.
305  TStreamerElement* element = sinfo->GetElement(id);
306  fStreamerType = element->GetType();
307  }
308 
309  //
310  // Handle varying-length datatypes by allocating an offsets array.
311  //
312  // The fBits part of a TObject is of varying length because the pidf
313  // is streamed only when the TObject is referenced by a TRef.
314  //
315 
316  fEntryOffsetLen = 0;
319  }
320 
321  //
322  // Make sure the basket is big enough to contain the
323  // entry offset array plus 100 bytes of data.
324  //
325 
326  if (basketsize < (100 + fEntryOffsetLen)) {
327  basketsize = 100 + fEntryOffsetLen;
328  }
329  fBasketSize = basketsize;
330 
331  //
332  // Allocate and initialize the basket control arrays.
333  //
334 
338 
339  for (Int_t i = 0; i < fMaxBaskets; ++i) {
340  fBasketBytes[i] = 0;
341  fBasketEntry[i] = 0;
342  fBasketSeek[i] = 0;
343  }
344 
345  // We need to keep track of the counter branch if we have
346  // one, since we cannot set it until we have created our
347  // leaf, which we do last.
348  TBranchElement* brOfCounter = 0;
349 
350  if (id < 0) {
351  // -- We are a top-level branch. Don't split a top-level branch, TTree::Bronch will do that work.
352  if (fBranchClass.GetClass()) {
353  Bool_t hasCustomStreamer = kFALSE;
354  Bool_t canSelfReference = CanSelfReference(fBranchClass);
355  if (fBranchClass.GetClass()->IsTObject()) {
356  if (canSelfReference) SetBit(kBranchObject);
358  } else {
359  if (canSelfReference) SetBit(kBranchAny);
361  }
362  if (hasCustomStreamer) {
363  fType = -1;
364  }
365  }
366  } else {
367  // -- We are a sub-branch of a split object.
368  TStreamerElement* element = sinfo->GetElement(id);
370  // -- If we are an object data member which inherits from TObject,
371  // flag it so that later during i/o we will register the object
372  // with the buffer so that pointers are handled correctly.
373  if (CanSelfReference(fBranchClass)) {
374  if (fBranchClass.GetClass()->IsTObject()) {
376  } else {
378  }
379  }
380  }
381  if (element->IsA() == TStreamerBasicPointer::Class()) {
382  // -- Fixup title with counter if we are a varying length array data member.
384  TString countname;
385  countname = bname;
386  Ssiz_t dot = countname.Last('.');
387  if (dot>=0) {
388  countname.Remove(dot+1);
389  } else {
390  countname = "";
391  }
392  countname += bp->GetCountName();
393  brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
394  countname.Form("%s[%s]",name.Data(),bp->GetCountName());
395  SetTitle(countname);
396 
397  } else if (element->IsA() == TStreamerLoop::Class()) {
398  // -- Fixup title with counter if we are a varying length array data member.
399  TStreamerLoop *bp = (TStreamerLoop *)element;
400  TString countname;
401  countname = bname;
402  Ssiz_t dot = countname.Last('.');
403  if (dot>=0) {
404  countname.Remove(dot+1);
405  } else {
406  countname = "";
407  }
408  countname += bp->GetCountName();
409  brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
410  countname.Form("%s[%s]",name.Data(),bp->GetCountName());
411  SetTitle(countname);
412 
413  }
414 
415  if (splitlevel > 0) {
416  // -- Create sub branches if requested by splitlevel.
417  const char* elem_type = element->GetTypeName();
419  if (element->CannotSplit()) {
420  fSplitLevel = 0;
421  } else if (element->IsA() == TStreamerBase::Class()) {
422  // -- We are a base class element.
423  // Note: This does not include an STL container class which is
424  // being used as a base class because the streamer element
425  // in that case is not the base streamer element it is the
426  // STL streamer element.
427  fType = 1;
428  TClass* clOfElement = TClass::GetClass(element->GetName());
429  Int_t nbranches = fBranches.GetEntriesFast();
430  // Note: The following code results in base class branches
431  // having two different cases for what their parent
432  // class will be, this is very annoying. It is also
433  // very annoying that the naming conventions for the
434  // sub-branch names are different as well.
435  if (!strcmp(name, clOfElement->GetName())) {
436  // -- If the branch's name is the same as the base class name,
437  // which happens when we are a child branch of a top-level
438  // branch whose name does not end in a dot and also has no
439  // internal dots, elide the branch name, and keep the branch
440  // heirarchy rooted at the ultimate parent, this keeps the base
441  // class part of the branch name from propagating downwards.
442  // FIXME: We are eliding the base class here, creating a break in the branch hierarchy.
443  // Note: We can use parent class (cltop) != branch class (elemClass) to detection elision.
444  Unroll("", fBranchClass.GetClass(), clOfElement, pointer, basketsize, splitlevel+splitSTLP, 0);
447  return;
448  }
449  // If the branch's name is not the same as the base class name,
450  // keep the branch name as a prefix (i.e., continue the branch
451  // heirarchy), but start a new class heirarchy at the base class.
452  //
453  // Note: If the parent branch was created by the branch constructor
454  // which takes a folder as a parameter, then this case will
455  // be used, because the branch name will be the same as the
456  // parent branch name.
457  // Note: This means that the sub-branches of a base class branch
458  // created by TTree::Bronch() have the base class name as
459  // as part of the branch name, while those created by
460  // Unroll() do not, ouch!!!
461  //
462  Unroll(name, clOfElement, clOfElement, pointer, basketsize, splitlevel+splitSTLP, 0);
463  if (strchr(bname, '.')) {
464  // Note: How can this happen?
465  // Answer: This is the case when using the new branch
466  // naming convention where the top-level branch ends in dot.
467  // Note: Well actually not entirely, we could also be a sub-branch
468  // of a split class, even when the top-level branch does not
469  // end in a dot.
470  // Note: Or the top-level branch could have been created by the
471  // branch constructor which takes a folder as input, in which
472  // case the top-level branch name will have internal dots
473  // representing the folder hierarchy.
476  return;
477  }
478  if (nbranches == fBranches.GetEntriesFast()) {
479  // -- 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.
480  if (strlen(bname)) {
481  name.Form("%s.%s", bname, clOfElement->GetName());
482  } else {
483  name.Form("%s", clOfElement->GetName());
484  }
485  SetName(name);
486  SetTitle(name);
487  }
490  return;
491  } else if (element->GetClassPointer() == TClonesArray::Class()) {
492  // -- We are a TClonesArray element.
493  Bool_t ispointer = element->IsaPointer();
494  TClonesArray *clones;
495  if (ispointer) {
496  char **ppointer = (char**)(pointer);
497  clones = (TClonesArray*)(*ppointer);
498  } else {
499  clones = (TClonesArray*)pointer;
500  }
501  // basket->DeleteEntryOffset(); //entryoffset not required for the clonesarray counter
502  fEntryOffsetLen = 0;
503  // ===> Create a leafcount
504  TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
505  fNleaves = 1;
506  fLeaves.Add(leaf);
507  fTree->GetListOfLeaves()->Add(leaf);
508  if (!clones) {
510  return;
511  }
512  TClass* clOfClones = clones->GetClass();
513  if (!clOfClones) {
516  return;
517  }
518  fType = 3;
519  // ===> create sub branches for each data member of a TClonesArray
520  //check that the contained objects class name is part of the element title
521  //This name is mandatory when reading the Tree later on and
522  //the parent class with the pointer to the TClonesArray is not available.
523  fClonesName = clOfClones->GetName();
524  fClonesClass = clOfClones;
525  TString aname;
526  aname.Form(" (%s)", clOfClones->GetName());
527  TString atitle = element->GetTitle();
528  if (!atitle.Contains(aname)) {
529  atitle += aname;
530  element->SetTitle(atitle.Data());
531  }
532  TString branchname( name );
533  branchname += "_";
534  SetTitle(branchname);
535  leaf->SetName(branchname);
536  leaf->SetTitle(branchname);
537  Unroll(name, clOfClones, clOfClones, pointer, basketsize, splitlevel+splitSTLP, 31);
538  BuildTitle(name);
541  return;
542  } else if (((fSTLtype >= ROOT::kSTLvector) && (fSTLtype < ROOT::kSTLend)) || ((fSTLtype > -ROOT::kSTLend) && (fSTLtype <= -ROOT::kSTLvector))) {
543  // -- We are an STL container element.
544  TClass* contCl = TClass::GetClass(elem_type);
545  fCollProxy = contCl->GetCollectionProxy()->Generate();
546  TClass* valueClass = GetCollectionProxy()->GetValueClass();
547  // Check to see if we can split the container.
548  Bool_t cansplit = kTRUE;
549  if (!valueClass) {
550  cansplit = kFALSE;
551  } else if ((valueClass == TString::Class()) || (valueClass == TClass::GetClass("string"))) {
552  cansplit = kFALSE;
553  } else if (GetCollectionProxy()->HasPointers() && !splitSTLP ) {
554  cansplit = kFALSE;
555  } else if (!valueClass->CanSplit() && !(GetCollectionProxy()->HasPointers() && splitSTLP)) {
556  cansplit = kFALSE;
557  } else if (valueClass->GetCollectionProxy()) {
558  // -- A collection was stored in a collection, we choose not to split it.
559  // Note: Splitting it would require extending TTreeFormula
560  // to understand how to access it.
561  cansplit = kFALSE;
562  }
563  if (cansplit) {
564  // -- Do the splitting work if we are allowed to.
565  fType = 4;
566  // Create a leaf for the master branch (the counter).
567  TLeaf *leaf = new TLeafElement(this, name, fID, fStreamerType);
568  fNleaves = 1;
569  fLeaves.Add(leaf);
570  fTree->GetListOfLeaves()->Add(leaf);
571  // Check that the contained objects class name is part of the element title.
572  // This name is mandatory when reading the tree later on and
573  // the parent class with the pointer to the STL container is not available.
574  fClonesName = valueClass->GetName();
575  fClonesClass = valueClass;
576  TString aname;
577  aname.Form(" (%s)", valueClass->GetName());
578  TString atitle = element->GetTitle();
579  if (!atitle.Contains(aname)) {
580  atitle += aname;
581  element->SetTitle(atitle.Data());
582  }
583  TString branchname (name);
584  branchname += "_";
585  SetTitle(branchname);
586  leaf->SetName(branchname);
587  leaf->SetTitle(branchname);
588  // Create sub branches for each data member of an STL container.
589  Unroll(name, valueClass, valueClass, pointer, basketsize, splitlevel+splitSTLP, 41);
590  BuildTitle(name);
593  return;
594  }
595  } else if (!strchr(elem_type, '*') && ((fStreamerType == TVirtualStreamerInfo::kObject) || (fStreamerType == TVirtualStreamerInfo::kAny))) {
596  // -- Create sub-branches for members that are classes.
597  //
598  // Note: This can only happen if we were called directly
599  // (usually by TClass::Bronch) because Unroll never
600  // calls us for an element of this type.
601  fType = 2;
602  TClass* clm = TClass::GetClass(elem_type);
603  Int_t err = Unroll(name, clm, clm, pointer, basketsize, splitlevel+splitSTLP, 0);
604  if (err >= 0) {
605  // Return on success.
606  // FIXME: Why not on error too?
609  return;
610  }
611  }
612  }
613  }
614 
615  //
616  // Create a leaf to represent this branch.
617  //
618 
619  TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
620  leaf->SetTitle(GetTitle());
621  fNleaves = 1;
622  fLeaves.Add(leaf);
623  fTree->GetListOfLeaves()->Add(leaf);
624 
625  //
626  // If we have a counter branch set it now that we have
627  // created our leaf, we cannot do it before then.
628  //
629 
630  if (brOfCounter) {
631  SetBranchCount(brOfCounter);
632  }
633 
636 }
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 /// Constructor when the branch object is a TClonesArray.
640 ///
641 /// If splitlevel > 0 this branch in turn is split into sub branches.
642 
643 TBranchElement::TBranchElement(TTree *tree, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
644 : TBranch()
645 , fClassName("TClonesArray")
646 , fParentName()
647 , fInfo((TStreamerInfo*)TClonesArray::Class()->GetStreamerInfo())
649 , fCurrentClass()
650 , fParentClass()
652 , fBranchID(-1)
655 , fIterators(0)
656 , fWriteIterators(0)
657 , fPtrIterators(0)
658 {
659  Init(tree, 0, bname, clones, basketsize, splitlevel, compress);
660 }
661 
662 ////////////////////////////////////////////////////////////////////////////////
663 /// Constructor when the branch object is a TClonesArray.
664 ///
665 /// If splitlevel > 0 this branch in turn is split into sub branches.
666 
667 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
668 : TBranch()
669 , fClassName("TClonesArray")
670 , fParentName()
671 , fInfo((TStreamerInfo*)TClonesArray::Class()->GetStreamerInfo())
673 , fCurrentClass()
674 , fParentClass()
676 , fBranchID(-1)
679 , fIterators(0)
680 , fWriteIterators(0)
681 , fPtrIterators(0)
682 {
683  Init(parent ? parent->GetTree() : 0, parent, bname, clones, basketsize, splitlevel, compress);
684 }
685 
686 ////////////////////////////////////////////////////////////////////////////////
687 /// Init when the branch object is a TClonesArray.
688 ///
689 /// If splitlevel > 0 this branch in turn is split into sub branches.
690 
691 void TBranchElement::Init(TTree *tree, TBranch *parent, const char* bname, TClonesArray* clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
692 {
693  fCollProxy = 0;
694  fSplitLevel = splitlevel;
695  fID = 0;
696  fInit = kTRUE;
697  fStreamerType = -1;
698  fType = 0;
699  fClassVersion = TClonesArray::Class()->GetClassVersion();
701  fBranchCount = 0;
702  fBranchCount2 = 0;
703  fObject = 0;
704  fOnfileObject = 0;
705  fMaximum = 0;
706  fBranchOffset = 0;
709 
710  fTree = tree;
711  fMother = parent ? parent->GetMother() : this;
712  fParent = parent;
714  fFileName = "";
715 
716  SetName(bname);
717  const char* name = GetName();
718  SetTitle(name);
719  //fClassName = fInfo->GetName();
720  fCompress = compress;
721  if (compress == -1 && fTree->GetDirectory()) {
722  TFile *bfile = fTree->GetDirectory()->GetFile();
723  if (bfile) fCompress = bfile->GetCompressionSettings();
724  }
725 
726  if (basketsize < 100) basketsize = 100;
727  fBasketSize = basketsize;
731 
732  for (Int_t i=0;i<fMaxBaskets;i++) {
733  fBasketBytes[i] = 0;
734  fBasketEntry[i] = 0;
735  fBasketSeek[i] = 0;
736  }
737 
738  // Reset the bit kAutoDelete to specify that when reading
739  // the object should not be deleted before calling the streamer.
741 
742  // create sub branches if requested by splitlevel
743  if (splitlevel%TTree::kSplitCollectionOfPointers > 0) {
744  TClass* clonesClass = clones->GetClass();
745  if (!clonesClass) {
746  Error("Init","Missing class object of the TClonesArray %s\n",clones->GetName());
747  return;
748  }
749  fType = 3;
750  // ===> Create a leafcount
751  TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
752  fNleaves = 1;
753  fLeaves.Add(leaf);
754  fTree->GetListOfLeaves()->Add(leaf);
755  // ===> create sub branches for each data member of a TClonesArray
756  fClonesName = clonesClass->GetName();
757  fClonesClass = clonesClass;
758  std::string branchname = name + std::string("_");
759  SetTitle(branchname.c_str());
760  leaf->SetName(branchname.c_str());
761  leaf->SetTitle(branchname.c_str());
762  Unroll(name, clonesClass, clonesClass, 0, basketsize, splitlevel, 31);
763  BuildTitle(name);
766  return;
767  }
768 
769  if (!clones->GetClass() || CanSelfReference(clones->GetClass())) {
771  }
772  TLeaf *leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
773  leaf->SetTitle(GetTitle());
774  fNleaves = 1;
775  fLeaves.Add(leaf);
776  fTree->GetListOfLeaves()->Add(leaf);
777 
780 }
781 
782 ////////////////////////////////////////////////////////////////////////////////
783 /// Constructor when the branch object is an STL collection.
784 ///
785 /// If splitlevel > 0 this branch in turn is split into sub branches.
786 
787 TBranchElement::TBranchElement(TTree *tree, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
788 : TBranch()
789 , fClassName(cont->GetCollectionClass()->GetName())
790 , fParentName()
792 , fCurrentClass()
793 , fParentClass()
794 , fBranchClass(cont->GetCollectionClass())
795 , fBranchID(-1)
798 , fIterators(0)
799 , fWriteIterators(0)
800 , fPtrIterators(0)
801 {
802  Init(tree, 0, bname, cont, basketsize, splitlevel, compress);
803 }
804 
805 ////////////////////////////////////////////////////////////////////////////////
806 /// Constructor when the branch object is an STL collection.
807 ///
808 /// If splitlevel > 0 this branch in turn is split into sub branches.
809 
810 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
811 : TBranch()
812 , fClassName(cont->GetCollectionClass()->GetName())
813 , fParentName()
815 , fCurrentClass()
816 , fParentClass()
817 , fBranchClass(cont->GetCollectionClass())
818 , fBranchID(-1)
821 , fIterators(0)
822 , fWriteIterators(0)
823 , fPtrIterators(0)
824 {
825  Init(parent ? parent->GetTree() : 0, parent, bname, cont, basketsize, splitlevel, compress);
826 }
827 
828 ////////////////////////////////////////////////////////////////////////////////
829 /// Init when the branch object is an STL collection.
830 ///
831 /// If splitlevel > 0 this branch in turn is split into sub branches.
832 
833 void TBranchElement::Init(TTree *tree, TBranch *parent, const char* bname, TVirtualCollectionProxy* cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
834 {
835  fCollProxy = cont->Generate();
836  TString name( bname );
837  if (name[name.Length()-1]=='.') {
838  name.Remove(name.Length()-1);
839  }
841  fSplitLevel = splitlevel;
842  fInfo = 0;
843  fID = -1;
844  fInit = kTRUE;
845  fStreamerType = -1; // TVirtualStreamerInfo::kSTLp;
846  fType = 0;
849  fBranchCount = 0;
850  fBranchCount2 = 0;
851  fObject = 0;
852  fOnfileObject = 0;
853  fMaximum = 0;
854  fBranchOffset = 0;
855 
856  //Must be set here so that write actions will be properly matched to the ReadLeavesPtr
857  fSTLtype = cont->GetCollectionType();
858  if (fSTLtype < 0) {
859  fSTLtype = -fSTLtype;
860  }
861 
862  fTree = tree;
863  fMother = parent ? parent->GetMother() : this;
864  fParent = parent;
866  fFileName = "";
867 
868  SetName(name);
869  SetTitle(name);
870  //fClassName = fBranchClass.GetClass()->GetName();
871  fCompress = compress;
872  if ((compress == -1) && fTree->GetDirectory()) {
873  TFile* bfile = fTree->GetDirectory()->GetFile();
874  if (bfile) {
876  }
877  }
878 
879  if (basketsize < 100) {
880  basketsize = 100;
881  }
882  fBasketSize = basketsize;
883 
887 
888  for (Int_t i = 0; i < fMaxBaskets; ++i) {
889  fBasketBytes[i] = 0;
890  fBasketEntry[i] = 0;
891  fBasketSeek[i] = 0;
892  }
893 
894  // Reset the bit kAutoDelete to specify that, when reading,
895  // the object should not be deleted before calling the streamer.
897 
898  // create sub branches if requested by splitlevel
900  (cont->HasPointers() && splitlevel > TTree::kSplitCollectionOfPointers && cont->GetValueClass() && cont->GetValueClass()->CanSplit() ) )
901  {
902  fType = 4;
903  // ===> Create a leafcount
904  TLeaf* leaf = new TLeafElement(this, name, fID, fStreamerType);
905  fNleaves = 1;
906  fLeaves.Add(leaf);
907  fTree->GetListOfLeaves()->Add(leaf);
908  // ===> create sub branches for each data member of an STL container value class
909  TClass* valueClass = cont->GetValueClass();
910  if (!valueClass) {
911  return;
912  }
913  fClonesName = valueClass->GetName();
914  fClonesClass = valueClass;
915  TString branchname( name );
916  branchname += "_";
917  SetTitle(branchname);
918  leaf->SetName(branchname);
919  leaf->SetTitle(branchname);
920  Unroll(name, valueClass, valueClass, 0, basketsize, splitlevel, 41);
921  BuildTitle(name);
924  return;
925  }
926 
927  TLeaf *leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
928  leaf->SetTitle(GetTitle());
929  fNleaves = 1;
930  fLeaves.Add(leaf);
931  fTree->GetListOfLeaves()->Add(leaf);
934 }
935 
936 ////////////////////////////////////////////////////////////////////////////////
937 /// Destructor.
938 
940 {
941  // Release any allocated I/O buffers.
942  if (fOnfileObject && TestBit(kOwnOnfileObj)) {
943  delete fOnfileObject;
944  fOnfileObject = 0;
945  }
946  ResetAddress();
947 
948  delete[] fBranchOffset;
949  fBranchOffset = 0;
950 
951  fInfo = 0;
952  fBranchCount2 = 0;
953  fBranchCount = 0;
954 
955  if (fType == 4 || fType == 0) {
956  // Only the top level TBranchElement containing an STL container,
957  // owns the collectionproxy.
958  delete fCollProxy;
959  }
960  fCollProxy = 0;
961 
962  delete fReadActionSequence;
963  delete fFillActionSequence;
964  delete fIterators;
965  delete fWriteIterators;
966  delete fPtrIterators;
967 }
968 
969 //
970 // This function is located here to allow inlining by the optimizer.
971 //
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Get streamer info for the branch class.
974 
976 {
977  // Note: we need to find a way to reduce the complexity of
978  // this often executed condition.
979  if (!fInfo || (fInfo && (!fInit || !fInfo->IsCompiled()))) {
980  const_cast<TBranchElement*>(this)->InitInfo();
981  }
982  return fInfo;
983 }
984 
985 ////////////////////////////////////////////////////////////////////////////////
986 /// Get streamer info for the branch class.
987 
989 {
990  return GetInfoImp();
991 }
992 
993 ////////////////////////////////////////////////////////////////////////////////
994 /// Browse the branch content.
995 
997 {
998  Int_t nbranches = fBranches.GetEntriesFast();
999  if (nbranches > 0) {
1000  TList persistentBranches;
1001  TBranch* branch=0;
1002  TIter iB(&fBranches);
1003  while((branch=(TBranch*)iB())) {
1004  if (branch->IsFolder()) persistentBranches.Add(branch);
1005  else {
1006  // only show branches corresponding to persistent members
1007  TClass* cl=0;
1008  if (strlen(GetClonesName()))
1009  // this works both for top level branches and for sub-branches,
1010  // as GetClonesName() is properly updated for sub-branches
1011  cl=fClonesClass;
1012  else {
1014 
1015  // check if we're in a sub-branch of this class
1016  // we can only find out asking the streamer given our ID
1017  TStreamerElement *element=0;
1018  TClass* clsub=0;
1019  if (fID>=0 && GetInfoImp()
1020  && GetInfoImp()->IsCompiled()
1021  && ((element=GetInfoImp()->GetElement(fID)))
1022  && ((clsub=element->GetClassPointer())))
1023  cl=clsub;
1024  }
1025  if (cl) {
1026  TString strMember=branch->GetName();
1027  Size_t mempos=strMember.Last('.');
1028  if (mempos!=kNPOS)
1029  strMember.Remove(0, (Int_t)mempos+1);
1030  mempos=strMember.First('[');
1031  if (mempos!=kNPOS)
1032  strMember.Remove((Int_t)mempos);
1033  TDataMember* m=cl->GetDataMember(strMember);
1034  if (!m || m->IsPersistent()) persistentBranches.Add(branch);
1035  } else persistentBranches.Add(branch);
1036  } // branch if not a folder
1037  }
1038  persistentBranches.Browse(b);
1039  // add all public const methods without params
1040  if (GetBrowsables() && GetBrowsables()->GetSize())
1041  GetBrowsables()->Browse(b);
1042  } else {
1043  if (GetBrowsables() && GetBrowsables()->GetSize()) {
1044  GetBrowsables()->Browse(b);
1045  return;
1046  }
1047  // Get the name and strip any extra brackets
1048  // in order to get the full arrays.
1049  TString slash("/");
1050  TString escapedSlash("\\/");
1051  TString name = GetName();
1052  Int_t pos = name.First('[');
1053  if (pos != kNPOS) {
1054  name.Remove(pos);
1055  }
1056  TString mothername;
1057  if (GetMother()) {
1058  mothername = GetMother()->GetName();
1059  pos = mothername.First('[');
1060  if (pos != kNPOS) {
1061  mothername.Remove(pos);
1062  }
1063  Int_t len = mothername.Length();
1064  if (len) {
1065  if (mothername(len-1) != '.') {
1066  // We do not know for sure whether the mother's name is
1067  // already preprended. So we need to check:
1068  // a) it is prepended
1069  // b) it is NOT the name of a daugher (i.e. mothername.mothername exist)
1070  TString doublename = mothername;
1071  doublename.Append(".");
1072  Int_t isthere = (name.Index(doublename) == 0);
1073  if (!isthere) {
1074  name.Prepend(doublename);
1075  } else {
1076  if (GetMother()->FindBranch(mothername)) {
1077  doublename.Append(mothername);
1078  isthere = (name.Index(doublename) == 0);
1079  if (!isthere) {
1080  mothername.Append(".");
1081  name.Prepend(mothername);
1082  }
1083  } else {
1084  // Nothing to do because the mother's name is
1085  // already in the name.
1086  }
1087  }
1088  } else {
1089  // If the mother's name end with a dot then
1090  // the daughter probably already contains the mother's name
1091  if (name.Index(mothername) == kNPOS) {
1092  name.Prepend(mothername);
1093  }
1094  }
1095  }
1096  }
1097  name.ReplaceAll(slash, escapedSlash);
1098  GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
1099  if (gPad) {
1100  gPad->Update();
1101  }
1102  }
1103 }
1104 
1105 ////////////////////////////////////////////////////////////////////////////////
1106 /// Set branch and leaf name and title in the case of a container sub-branch.
1107 
1109 {
1110  TString branchname;
1111 
1112  Int_t nbranches = fBranches.GetEntries();
1113 
1114  for (Int_t i = 0; i < nbranches; ++i) {
1116  if (fType == 3) {
1117  bre->SetType(31);
1118  } else if (fType == 4) {
1119  bre->SetType(41);
1120  } else {
1121  Error("BuildTitle", "This cannot happen, fType of parent is not 3 or 4!");
1122  }
1123  bre->fCollProxy = GetCollectionProxy();
1124  bre->BuildTitle(name);
1125  const char* fin = strrchr(bre->GetTitle(), '.');
1126  if (fin == 0) {
1127  continue;
1128  }
1129  // The branch counter for a sub-branch of a container is the container master branch.
1130  bre->SetBranchCount(this);
1131  TLeafElement* lf = (TLeafElement*) bre->GetListOfLeaves()->At(0);
1132  // If branch name is of the form fTracks.fCovar[3][4], then
1133  // set the title to fCovar[fTracks_].
1134  branchname = fin+1;
1135  Ssiz_t dim = branchname.First('[');
1136  if (dim>=0) {
1137  branchname.Remove(dim);
1138  }
1139  branchname += TString::Format("[%s_]",name);
1140  bre->SetTitle(branchname);
1141  if (lf) {
1142  lf->SetTitle(branchname);
1143  }
1144  // Is there a secondary branchcount?
1145  //
1146  // fBranchCount2 points to the secondary branchcount
1147  // in case a TClonesArray element itself has a branchcount.
1148  //
1149  // Example: In Event class with TClonesArray fTracks of Track objects.
1150  // if the Track object has two members
1151  // Int_t fNpoint;
1152  // Float_t *fPoints; //[fNpoint]
1153  // In this case the TBranchElement fTracks.fPoints has
1154  // -its primary branchcount pointing to the branch fTracks
1155  // -its secondary branchcount pointing to fTracks.fNpoint
1156  Int_t stype = bre->GetStreamerType();
1157  // FIXME: Should 60 be included here?
1158  if ((stype > 40) && (stype < 61)) {
1159  TString name2 (bre->GetName());
1160  Ssiz_t bn = name2.Last('.');
1161  if (bn<0) {
1162  continue;
1163  }
1164  TStreamerBasicPointer *el = (TStreamerBasicPointer*)bre->GetInfoImp()->GetElements()->FindObject(name2.Data()+bn+1);
1165  name2.Remove(bn+1);
1166  if (el) name2 += el->GetCountName();
1168  bre->SetBranchCount2(bc2);
1169  }
1170  bre->SetReadLeavesPtr();
1171  bre->SetFillLeavesPtr();
1172  }
1173 }
1174 
1175 ////////////////////////////////////////////////////////////////////////////////
1176 /// Loop on all leaves of this branch to fill the basket buffer.
1177 ///
1178 /// The function returns the number of bytes committed to the
1179 /// individual branches. If a write error occurs, the number of
1180 /// bytes returned is -1. If no data are written, because, e.g.,
1181 /// the branch is disabled, the number of bytes returned is 0.
1182 ///
1183 /// Note: We not not use any member functions from TLeafElement!
1184 
1186 {
1187  Int_t nbytes = 0;
1188  Int_t nwrite = 0;
1189  Int_t nerror = 0;
1190  Int_t nbranches = fBranches.GetEntriesFast();
1191 
1192  ValidateAddress();
1193 
1194  //
1195  // If we are a top-level branch, update addresses.
1196  //
1197 
1198  if (fID < 0) {
1199  if (!fObject) {
1200  Error("Fill", "attempt to fill branch %s while addresss is not set", GetName());
1201  return 0;
1202  }
1203  }
1204 
1205  //
1206  // If the tree has a TRefTable, set the current branch if
1207  // branch is not a basic type.
1208  //
1209 
1210  // FIXME: This test probably needs to be extended past 10.
1211  if ((fType >= -1) && (fType < 10)) {
1212  TBranchRef* bref = fTree->GetBranchRef();
1213  if (bref) {
1214  fBranchID = bref->SetParent(this, fBranchID);
1215  }
1216  }
1217 
1218  if (!nbranches) {
1219  // No sub-branches.
1220  if (!TestBit(kDoNotProcess)) {
1221  nwrite = TBranch::Fill();
1222  if (nwrite < 0) {
1223  Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
1224  ++nerror;
1225  } else {
1226  nbytes += nwrite;
1227  }
1228  }
1229  } else {
1230  // We have sub-branches.
1231  if (fType == 3 || fType == 4) {
1232  // TClonesArray or STL container counter
1233  nwrite = TBranch::Fill();
1234  if (nwrite < 0) {
1235  Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
1236  ++nerror;
1237  } else {
1238  nbytes += nwrite;
1239  }
1240  } else {
1241  ++fEntries;
1242  }
1243  for (Int_t i = 0; i < nbranches; ++i) {
1244  TBranchElement* branch = (TBranchElement*) fBranches[i];
1245  if (!branch->TestBit(kDoNotProcess)) {
1246  nwrite = branch->Fill();
1247  if (nwrite < 0) {
1248  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d", GetName(), branch->GetName(), nwrite);
1249  nerror++;
1250  } else {
1251  nbytes += nwrite;
1252  }
1253  }
1254  }
1255  }
1256 
1257  if (fTree->Debug() > 0) {
1258  // Debugging.
1259  Long64_t entry = fEntries;
1260  if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
1261  printf("Fill: %lld, branch=%s, nbytes=%d\n", entry, GetName(), nbytes);
1262  }
1263  }
1264 
1265  if (nerror != 0) {
1266  return -1;
1267  }
1268 
1269  return nbytes;
1270 }
1271 
1272 ////////////////////////////////////////////////////////////////////////////////
1273 /// Write leaves into i/o buffers for this branch.
1274 /// For the case where the branch is set in MakeClass mode (decomposed object).
1275 
1277 {
1278  ValidateAddress();
1279 
1280  //
1281  // Silently do nothing if we have no user i/o buffer.
1282  //
1283 
1284  if (!fObject) {
1285  return;
1286  }
1287 
1288  // -- TClonesArray top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1289  if(fType == 3) {
1290  // fClonesClass can not be zero since we are of type 3, see TBranchElement::Init
1292  if (!si) {
1293  Error("FillLeaves", "Cannot get streamer info for branch '%s' class '%s'", GetName(), fClonesClass->GetName());
1294  return;
1295  }
1296  b.ForceWriteInfo(si,kFALSE);
1297  Int_t* nptr = (Int_t*) fAddress;
1298  b << *nptr;
1299  } else if (fType == 31) {
1300  // -- TClonesArray sub-branch. Write out the entries in the TClonesArray.
1301  // -- A MakeClass() tree, we must use fAddress instead of fObject.
1302  if (!fAddress) {
1303  // FIXME: Enable this message.
1304  //Error("FillLeaves", "Branch address not set for branch '%s'!", GetName());
1305  return;
1306  }
1307  Int_t atype = fStreamerType;
1308  if (atype > 54) {
1309  // Note: We are not supporting kObjectp, kAny, kObjectp,
1310  // kObjectP, kTString, kTObject, kTNamed, kAnyp,
1311  // kAnyP, kSTLp, kSTL, kSTLstring, kStreamer,
1312  // kStreamLoop here, nor pointers to varying length
1313  // arrays of them either.
1314  // Nor do we support pointers to varying length
1315  // arrays of kBits, kLong64, kULong64, nor kBool.
1316  return;
1317  }
1319  if (!nn) {
1320  Error("FillLeaves", "The branch counter address was zero!");
1321  return;
1322  }
1323  Int_t n = *nn;
1324  if (atype > 40) {
1325  // Note: We are not supporting pointer to varying length array.
1326  Error("FillLeaves", "Clonesa: %s, n=%d, sorry not supported yet", GetName(), n);
1327  return;
1328  }
1329  if (atype > 20) {
1330  atype -= 20;
1332  n = n * leaf->GetLenStatic();
1333  }
1334  switch (atype) {
1335  // Note: Type 0 is a base class and cannot happen here, see Unroll().
1336  case TVirtualStreamerInfo::kChar /* 1 */: { b.WriteFastArray((Char_t*) fAddress, n); break; }
1337  case TVirtualStreamerInfo::kShort /* 2 */: { b.WriteFastArray((Short_t*) fAddress, n); break; }
1338  case TVirtualStreamerInfo::kInt /* 3 */: { b.WriteFastArray((Int_t*) fAddress, n); break; }
1339  case TVirtualStreamerInfo::kLong /* 4 */: { b.WriteFastArray((Long_t*) fAddress, n); break; }
1340  case TVirtualStreamerInfo::kFloat /* 5 */: { b.WriteFastArray((Float_t*) fAddress, n); break; }
1341  case TVirtualStreamerInfo::kCounter /* 6 */: { b.WriteFastArray((Int_t*) fAddress, n); break; }
1342  // FIXME: We do nothing with type 7 (TVirtualStreamerInfo::kCharStar, char*) here!
1343  case TVirtualStreamerInfo::kDouble /* 8 */: { b.WriteFastArray((Double_t*) fAddress, n); break; }
1344  case TVirtualStreamerInfo::kDouble32 /* 9 */: {
1346  // coverity[returned_null] structurally si->fComp (used in GetElem) can not be null.
1347  TStreamerElement* se = si->GetElement(fID);
1348  Double_t* xx = (Double_t*) fAddress;
1349  for (Int_t ii = 0; ii < n; ++ii) {
1350  b.WriteDouble32(&(xx[ii]),se);
1351  }
1352  break;
1353  }
1354  case TVirtualStreamerInfo::kFloat16 /* 19 */: {
1356  // coverity[dereference] structurally si can not be null.
1358  Float_t* xx = (Float_t*) fAddress;
1359  for (Int_t ii = 0; ii < n; ++ii) {
1360  b.WriteFloat16(&(xx[ii]),se);
1361  }
1362  break;
1363  }
1364  // Note: Type 10 is unused for now.
1365  case TVirtualStreamerInfo::kUChar /* 11 */: { b.WriteFastArray((UChar_t*) fAddress, n); break; }
1366  case TVirtualStreamerInfo::kUShort /* 12 */: { b.WriteFastArray((UShort_t*) fAddress, n); break; }
1367  case TVirtualStreamerInfo::kUInt /* 13 */: { b.WriteFastArray((UInt_t*) fAddress, n); break; }
1368  case TVirtualStreamerInfo::kULong /* 14 */: { b.WriteFastArray((ULong_t*) fAddress, n); break; }
1369  // FIXME: This is wrong!!! TVirtualStreamerInfo::kBits is a variable length type.
1370  case TVirtualStreamerInfo::kBits /* 15 */: { b.WriteFastArray((UInt_t*) fAddress, n); break; }
1371  case TVirtualStreamerInfo::kLong64 /* 16 */: { b.WriteFastArray((Long64_t*) fAddress, n); break; }
1372  case TVirtualStreamerInfo::kULong64 /* 17 */: { b.WriteFastArray((ULong64_t*) fAddress, n); break; }
1373  case TVirtualStreamerInfo::kBool /* 18 */: { b.WriteFastArray((Bool_t*) fAddress, n); break; }
1374  }
1375  }
1376 }
1377 
1378 ////////////////////////////////////////////////////////////////////////////////
1379 /// Write leaves into i/o buffers for this branch.
1380 /// Case of a collection (fType == 4).
1381 
1383 {
1384  // -- STL container top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1385  ValidateAddress();
1386 
1387  //
1388  // Silently do nothing if we have no user i/o buffer.
1389  //
1390 
1391  if (!fObject) {
1392  return;
1393  }
1394 
1396  Int_t n = 0;
1397  // We are in a block so the helper pops as soon as possible.
1399  n = proxy->Size();
1400 
1401  if (n > fMaximum) {
1402  fMaximum = n;
1403  }
1404  b << n;
1405 
1408  } else {
1409  //NOTE: this does not work for not vectors since the CreateIterators expects a TGenCollectionProxy::TStaging as its argument!
1410  //NOTE: and those not work in general yet, since the TStaging object is neither created nor passed.
1411  // We need to review how to avoid the need for a TStaging during the writing.
1414  } else {
1416  }
1417  }
1418 
1419 }
1420 
1421 ////////////////////////////////////////////////////////////////////////////////
1422 /// Write leaves into i/o buffers for this branch.
1423 /// Case of a data member within a collection (fType == 41).
1424 
1426 {
1427  ValidateAddress();
1428 
1429  //
1430  // Silently do nothing if we have no user i/o buffer.
1431  //
1432 
1433  if (!fObject) {
1434  return;
1435  }
1436 
1437  // FIXME: This wont work if a pointer to vector is split!
1439  // Note: We cannot pop the proxy here because we need it for the i/o.
1441  if (!si) {
1442  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1443  return;
1444  }
1445 
1447  R__ASSERT(0!=iter);
1449 }
1450 
1451 ////////////////////////////////////////////////////////////////////////////////
1452 /// Write leaves into i/o buffers for this branch.
1453 /// Case of a data member within a collection (fType == 41).
1454 
1456 {
1457  ValidateAddress();
1458 
1459  //
1460  // Silently do nothing if we have no user i/o buffer.
1461  //
1462 
1463  if (!fObject) {
1464  return;
1465  }
1466 
1467  // FIXME: This wont work if a pointer to vector is split!
1469 
1470  // Note: We cannot pop the proxy here because we need it for the i/o.
1472  if (!si) {
1473  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1474  return;
1475  }
1476 
1478  b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1479 
1480 }
1481 
1482 ////////////////////////////////////////////////////////////////////////////////
1483 /// Write leaves into i/o buffers for this branch.
1484 /// Case of a data member within a collection (fType == 41).
1485 
1487 {
1488  ValidateAddress();
1489 
1490  //
1491  // Silently do nothing if we have no user i/o buffer.
1492  //
1493 
1494  if (!fObject) {
1495  return;
1496  }
1497 
1498  // FIXME: This wont work if a pointer to vector is split!
1500  // Note: We cannot pop the proxy here because we need it for the i/o.
1502  if (!si) {
1503  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1504  return;
1505  }
1506 
1508  R__ASSERT(0!=iter);
1509  b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1510 
1511 }
1512 
1513 ////////////////////////////////////////////////////////////////////////////////
1514 /// Write leaves into i/o buffers for this branch.
1515 /// Case of a data member within a collection (fType == 41).
1516 
1518 {
1519  ValidateAddress();
1520 
1521  //
1522  // Silently do nothing if we have no user i/o buffer.
1523  //
1524 
1525  if (!fObject) {
1526  return;
1527  }
1528 
1529  // FIXME: This wont work if a pointer to vector is split!
1531  // Note: We cannot pop the proxy here because we need it for the i/o.
1533  if (!si) {
1534  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1535  return;
1536  }
1537 
1539  R__ASSERT(0!=iter);
1540  b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1541 
1542 }
1543 
1544 ////////////////////////////////////////////////////////////////////////////////
1545 /// Write leaves into i/o buffers for this branch.
1546 /// Case of a TClonesArray (fType == 3).
1547 
1549 {
1550  // -- TClonesArray top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1551  ValidateAddress();
1552 
1553  //
1554  // Silently do nothing if we have no user i/o buffer.
1555  //
1556 
1557  if (!fObject) {
1558  return;
1559  }
1560 
1561  TClonesArray* clones = (TClonesArray*) fObject;
1562  Int_t n = clones->GetEntriesFast();
1563  if (n > fMaximum) {
1564  fMaximum = n;
1565  }
1566  b << n;
1567 }
1568 
1569 ////////////////////////////////////////////////////////////////////////////////
1570 /// Write leaves into i/o buffers for this branch.
1571 /// Case of a data member within a TClonesArray (fType == 31).
1572 
1574 {
1575  ValidateAddress();
1576 
1577  //
1578  // Silently do nothing if we have no user i/o buffer.
1579  //
1580 
1581  if (!fObject) {
1582  return;
1583  }
1584 
1585  TClonesArray* clones = (TClonesArray*) fObject;
1586  Int_t n = clones->GetEntriesFast();
1588  if (!si) {
1589  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1590  return;
1591  }
1592 
1593  char **arr = (char **)clones->GetObjectRef(0);
1594  char **end = arr + n;
1596 }
1597 
1598 ////////////////////////////////////////////////////////////////////////////////
1599 /// Write leaves into i/o buffers for this branch.
1600 /// Case of a non TObject, non collection class with a custom streamer
1601 
1603 {
1604  ValidateAddress();
1605 
1606  //
1607  // Silently do nothing if we have no user i/o buffer.
1608  //
1609 
1610  if (!fObject) {
1611  return;
1612  }
1613 
1614  //
1615  // Remember tobjects written to the buffer so that
1616  // pointers are handled correctly later.
1617 
1618  if (TestBit(kBranchObject)) {
1619  b.MapObject((TObject*) fObject);
1620  } else if (TestBit(kBranchAny)) {
1622  }
1623 
1625 }
1626 
1627 ////////////////////////////////////////////////////////////////////////////////
1628 /// Write leaves into i/o buffers for this branch.
1629 /// For split-class branch, base class branch, data member branch, or top-level branch.
1630 /// which do have a branch count and are not a counter.
1631 
1633 {
1634  FillLeavesMember(b);
1635  /*
1636  ValidateAddress();
1637 
1638  //
1639  // Silently do nothing if we have no user i/o buffer.
1640  //
1641 
1642  if (!fObject) {
1643  return;
1644  }
1645  */
1646 }
1647 
1648 ////////////////////////////////////////////////////////////////////////////////
1649 /// Write leaves into i/o buffers for this branch.
1650 /// For split-class branch, base class branch, data member branch, or top-level branch.
1651 /// which do not have a branch count and are a counter.
1652 
1654 {
1655  ValidateAddress();
1656 
1657  //
1658  // Silently do nothing if we have no user i/o buffer.
1659  //
1660 
1661  if (!fObject) {
1662  return;
1663  }
1664  // -- Top-level, data member, base class, or split class branch.
1665  // 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.
1666  // Note: A split top-level branch (0, and fID == -2) should not happen here, see Fill().
1667  // FIXME: What happens with a split base class branch,
1668  // or a split class branch???
1669  TStreamerInfo* si = GetInfoImp();
1670  if (!si) {
1671  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1672  return;
1673  }
1674  // Since info is not null, fFillActionSequence is not null either.
1676  // Int_t n = si->WriteBufferAux(b, &fObject, fID, 1, 0, 0);
1677 
1678  Int_t n = *(Int_t*)(fObject + si->TStreamerInfo::GetElementOffset(fID)); // or GetInfoImp()->GetTypedValue<Int_t>(&fObject, fID, j, -1);
1679  if (n > fMaximum) {
1680  fMaximum = n;
1681  }
1682 
1683 }
1684 
1685 ////////////////////////////////////////////////////////////////////////////////
1686 /// Write leaves into i/o buffers for this branch.
1687 /// For split-class branch, base class branch, data member branch, or top-level branch.
1688 /// which do not have a branch count and are not a counter.
1689 
1691 {
1692  ValidateAddress();
1693 
1694  //
1695  // Silently do nothing if we have no user i/o buffer.
1696  //
1697 
1698  if (!fObject) {
1699  return;
1700  }
1701 
1702  if (TestBit(kBranchObject)) {
1703  b.MapObject((TObject*) fObject);
1704  } else if (TestBit(kBranchAny)) {
1706  }
1707 
1708  // -- Top-level, data member, base class, or split class branch.
1709  // 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.
1710  // Note: A split top-level branch (0, and fID == -2) should not happen here, see Fill().
1711  // FIXME: What happens with a split base class branch,
1712  // or a split class branch???
1713  TStreamerInfo* si = GetInfoImp();
1714  if (!si) {
1715  Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1716  return;
1717  }
1718  // Since info is not null, fFillActionSequence is not null either.
1720 
1721 }
1722 
1723 ////////////////////////////////////////////////////////////////////////////////
1724 /// Remove trailing dimensions and make sure
1725 /// there is a trailing dot.
1726 
1727 static void R__CleanName(std::string &name)
1728 {
1729  if (name[name.length()-1]==']') {
1730  std::size_t dim = name.find_first_of("[");
1731  if (dim != std::string::npos) {
1732  name.erase(dim);
1733  }
1734  }
1735  if (name[name.size()-1] != '.') {
1736  name += '.';
1737  }
1738 }
1739 
1740 ////////////////////////////////////////////////////////////////////////////////
1741 /// Find the immediate sub-branch with passed name.
1742 
1744 {
1745  // The default behavior of TBranch::FindBranch is sometimes
1746  // incorrect if this branch represent a base class, since
1747  // the base class name might or might not be in the name
1748  // of the sub-branches and might or might not be in the
1749  // name being passed.
1750 
1751  if (fID >= 0) {
1753  TStreamerElement* se = si->GetElement(fID);
1754  if (se && se->IsBase()) {
1755  // We allow the user to pass only the last dotted component of the name.
1756  UInt_t len = strlen(name);
1757  std::string longnm;
1758  longnm.reserve(fName.Length()+len+3); // Enough space of fName + name + dots
1759  longnm = fName.Data();
1760  R__CleanName(longnm);
1761  longnm += name;
1762  std::string longnm_parent;
1763  longnm_parent.reserve(fName.Length()+len+3);
1764  longnm_parent = (GetMother()->GetSubBranch(this)->GetName());
1765  R__CleanName(longnm_parent);
1766  longnm_parent += name; // Name without the base class name
1767 
1768  UInt_t namelen = strlen(name);
1769 
1770  TBranch* branch = 0;
1771  Int_t nbranches = fBranches.GetEntries();
1772  for(Int_t i = 0; i < nbranches; ++i) {
1773  branch = (TBranch*) fBranches.UncheckedAt(i);
1774 
1775  const char *brname = branch->GetName();
1776  UInt_t brlen = strlen(brname);
1777  if (brname[brlen-1]==']') {
1778  const char *dim = strchr(brname,'[');
1779  if (dim) {
1780  brlen = dim - brname;
1781  }
1782  }
1783  if (namelen == brlen /* same effective size */
1784  && strncmp(name,brname,brlen) == 0) {
1785  return branch;
1786  }
1787  if (brlen == longnm.length()
1788  && strncmp(longnm.c_str(),brname,brlen) == 0) {
1789  return branch;
1790  }
1791  // This check is specific to base class
1792  if (brlen == longnm_parent.length()
1793  && strncmp(longnm_parent.c_str(),brname,brlen) == 0) {
1794  return branch;
1795  }
1796 
1797  if (namelen>brlen && name[brlen]=='.' && strncmp(name,brname,brlen)==0) {
1798  // The prefix subbranch name match the branch name.
1799  return branch->FindBranch(name+brlen+1);
1800  }
1801  }
1802  }
1803  }
1805  if (!result) {
1806  // Look in base classes if any
1807  Int_t nbranches = fBranches.GetEntries();
1808  for(Int_t i = 0; i < nbranches; ++i) {
1809  TObject *obj = fBranches.UncheckedAt(i);
1810  if(obj->IsA() != TBranchElement :: Class() )
1811  continue;
1812  TBranchElement *br = (TBranchElement*)obj;
1813  TVirtualStreamerInfo* si = br->GetInfoImp();
1814  if (si && br->GetID() >= 0) {
1815  TStreamerElement* se = si->GetElement(br->GetID());
1816  if (se && se->IsBase()) {
1817  result = br->FindBranch(name);
1818  }
1819  }
1820  }
1821  }
1822  return result;
1823 }
1824 
1825 ////////////////////////////////////////////////////////////////////////////////
1826 /// Find the leaf corresponding to the name 'searchname'.
1827 
1829 {
1830  TLeaf *leaf = TBranch::FindLeaf(name);
1831 
1832  if (leaf==0 && GetListOfLeaves()->GetEntries()==1) {
1833  TBranch *br = GetMother()->GetSubBranch( this );
1834  if( br->IsA() != TBranchElement::Class() )
1835  return 0;
1836 
1837  TBranchElement *parent = (TBranchElement*)br;
1838  if (parent==this || parent->GetID()<0 ) return 0;
1839 
1840  TVirtualStreamerInfo* si = parent->GetInfoImp();
1841  TStreamerElement* se = si->GetElement(parent->GetID());
1842 
1843  if (! se->IsBase() ) return 0;
1844 
1845  br = GetMother()->GetSubBranch( parent );
1846  if( br->IsA() != TBranchElement::Class() )
1847  return 0;
1848 
1849  TBranchElement *grand_parent = (TBranchElement*)br;
1850 
1851  std::string longname( grand_parent->GetName() );
1852  R__CleanName(longname);
1853  longname += name;
1854 
1855  std::string leafname( GetListOfLeaves()->At(0)->GetName() );
1856 
1857  if ( longname == leafname ) {
1858  return (TLeaf*)GetListOfLeaves()->At(0);
1859  }
1860  }
1861  return leaf;
1862 }
1863 
1864 ////////////////////////////////////////////////////////////////////////////////
1865 /// Get the branch address.
1866 ///
1867 /// If we are *not* owned by a MakeClass() tree:
1868 ///
1869 /// - If we are a top-level branch, return a pointer
1870 /// - to the pointer to our object.
1871 ///
1872 /// If we are *not* a top-level branch, return a pointer
1873 /// to our object.
1874 ///
1875 /// If we are owned by a MakeClass() tree:
1876 ///
1877 /// - Return a pointer to our object.
1878 
1880 {
1881  ValidateAddress();
1882  return fAddress;
1883 }
1884 
1885 ////////////////////////////////////////////////////////////////////////////////
1886 /// Init the streamer info for the branch class, try to compensate for class
1887 /// code unload/reload and schema evolution.
1888 
1890 {
1891  if (!fInfo) {
1892  // We did not already have streamer info, so now we must find it.
1893  TClass* cl = fBranchClass.GetClass();
1894 
1895  //------------------------------------------------------------------------
1896  // Check if we're dealing with the name change
1897  //////////////////////////////////////////////////////////////////////////
1898 
1899  TClass* targetClass = 0;
1900  if( fTargetClass.GetClassName()[0] ) {
1901  targetClass = fTargetClass;
1902  if (!targetClass && GetCollectionProxy()) {
1903  // We are in the case where the branch holds a custom collection
1904  // proxy but the dictionary is not loaded, calling
1905  // GetCollectionProxy had the side effect of creating the TClass
1906  // corresponding to this emulated collection.
1907  targetClass = fTargetClass;
1908  }
1909  if ( !targetClass ) {
1910  Error( "InitInfo", "The target class dictionary is not present!" );
1911  return;
1912  }
1913  } else {
1914  targetClass = cl;
1915  }
1916  if (cl) {
1917  //---------------------------------------------------------------------
1918  // Get the streamer info for given version
1919  ///////////////////////////////////////////////////////////////////////
1920 
1921  {
1922  if ( (cl->Property() & kIsAbstract) && cl == targetClass) {
1923  TBranchElement *parent = (TBranchElement*)GetMother()->GetSubBranch(this);
1924  if (parent && parent != this && !parent->GetClass()->IsLoaded() ) {
1925  // Our parent's class is emulated and we represent an abstract class.
1926  // and the target class has not been set explicilty.
1927  TString target = cl->GetName();
1928  target += "@@emulated";
1929  fTargetClass.SetName(target);
1930 
1931  if (!fTargetClass) {
1933  }
1934  targetClass = fTargetClass;
1935  }
1936  }
1937  if( targetClass != cl ) {
1939  } else {
1941  }
1942  }
1943 
1944  // FIXME: Check that the found streamer info checksum matches our branch class checksum here.
1945  // Check to see if the class code was unloaded/reloaded
1946  // since we were created.
1948  if (fCheckSum && (cl->IsForeign() || (!cl->IsLoaded() && (fClassVersion == 1) && cl->GetStreamerInfos()->At(1) && (fCheckSum != ((TVirtualStreamerInfo*) cl->GetStreamerInfos()->At(1))->GetCheckSum())))) {
1949  // Try to compensate for a class that got unloaded on us.
1950  // Search through the streamer infos by checksum
1951  // and take the first match.
1952 
1953  TStreamerInfo* info;
1954  if( targetClass != cl )
1955  info = (TStreamerInfo*)targetClass->GetConversionStreamerInfo( cl, fCheckSum );
1956  else {
1957  info = (TStreamerInfo*)cl->FindStreamerInfo( fCheckSum );
1958  if (info) {
1959  // Now that we found it, we need to make sure it is initialize (Find does not initialize the StreamerInfo).
1960  info = (TStreamerInfo*)cl->GetStreamerInfo(info->GetClassVersion());
1961  }
1962  }
1963  if( info ) {
1964  fInfo = info;
1965  // We no longer reset the class version so that in case the user is passing us later
1966  // the address of a class that require (another) Conversion we can find the proper
1967  // StreamerInfo.
1968  // fClassVersion = fInfo->GetClassVersion();
1969  }
1970  }
1971  }
1972  }
1973 
1974  //
1975  // Fixup cached streamer info if necessary.
1976  //
1977  // FIXME: What if the class code was unloaded/reloaded since we were cached?
1978 
1979  if (fInfo) {
1980 
1981  if (!fInfo->IsCompiled()) {
1982  // Streamer info has not yet been compiled.
1983 
1984  Error("InitInfo","StreamerInfo is not compiled.");
1985  }
1986  if (!fInit) {
1987  // We were read in from a file, figure out what our fID should be,
1988  // schema evolution must be considered.
1989  //
1990  // Force our fID to be the id of the first streamer element that matches our name.
1991  //
1992  if (GetID() > -1) {
1993  // We are *not* a top-level branch.
1994  std::string s(GetName());
1995  size_t pos = s.rfind('.');
1996  if (pos != std::string::npos) {
1997  s = s.substr(pos+1);
1998  }
1999  while ((pos = s.rfind('[')) != std::string::npos) {
2000  s = s.substr(0, pos);
2001  }
2002  int offset = 0;
2003  TStreamerElement* elt = fInfo->GetStreamerElement(s.c_str(), offset);
2004  if (elt && offset!=TStreamerInfo::kMissing) {
2005  size_t ndata = fInfo->GetNelement();
2006  fIDs.clear();
2007  for (size_t i = 0; i < ndata; ++i) {
2008  if (fInfo->GetElement(i) == elt) {
2010  && (i+1) < ndata
2011  && s == fInfo->GetElement(i)->GetName())
2012  {
2013  // If the TStreamerElement we found is storing the information in the
2014  // cache and is a repeater, we need to use the real one (the next one).
2015  // (At least until the cache/repeat mechanism is properly handle by
2016  // ReadLeaves).
2017  // fID = i+1;
2018  fID = i;
2019  if (elt->TestBit(TStreamerElement::kRepeat)) {
2020  fIDs.push_back(fID+1);
2021  } else if (fInfo->GetElement(i+1)->TestBit(TStreamerElement::kWrite)) {
2022  fIDs.push_back(fID+1);
2023  }
2024  } else {
2025  fID = i;
2026  }
2027  if (elt->TestBit (TStreamerElement::kCache)) {
2029  }
2030  break;
2031  }
2032  }
2033  for (size_t i = fID+1+(fIDs.size()); i < ndata; ++i) {
2034  TStreamerElement *nextel = fInfo->GetElement(i);
2035  // Add all (and only) the Artificial Elements that follows this StreamerInfo.
2036  if (fType==31||fType==41) {
2037  // The nested objects are unfolded and their branch can not be used to
2038  // execute StreamerElements of this StreamerInfo.
2039  if (nextel->GetType() == TStreamerInfo::kObject
2040  || nextel->GetType() == TStreamerInfo::kAny) {
2041  continue;
2042  }
2043  }
2044  if (nextel->GetOffset() == TStreamerInfo::kMissing) {
2045  // This element will be 'skipped', it's TBranchElement's fObject will null
2046  // and thus can not be used to execute the artifical StreamerElements
2047  continue;
2048  }
2049  if (nextel->IsA() != TStreamerArtificial::Class()
2050  || nextel->GetType() == TStreamerInfo::kCacheDelete ) {
2051  break;
2052  }
2053  fIDs.push_back(i);
2054  }
2055  } else if (elt && offset==TStreamerInfo::kMissing) {
2056  // Still re-assign fID properly.
2057  fIDs.clear();
2058  size_t ndata = fInfo->GetNelement();
2059  for (size_t i = 0; i < ndata; ++i) {
2060  if (fInfo->GetElement(i) == elt) {
2061  fID = i;
2062  break;
2063  }
2064  }
2065  } else {
2066  // We have not even found the element .. this is strange :(
2067  // fIDs.clear();
2068  // fID = -3;
2069  // SetBit(kDoNotProcess);
2070  }
2071  if (fOnfileObject==0 && (fType==31 || fType==41 || (0 <= fType && fType <=2) ) && fInfo->GetNelement()
2073  {
2074  Int_t arrlen = 1;
2075  if (fType==31 || fType==41) {
2076  TLeaf *leaf = (TLeaf*)fLeaves.At(0);
2077  if (leaf) {
2078  arrlen = leaf->GetMaximum();
2079  }
2080  }
2081  fOnfileObject = new TVirtualArray( fInfo->GetElement(0)->GetClassPointer(), arrlen );
2082  // Propage this to all the other branch of this type.
2083  TObjArray *branches = GetMother()->GetSubBranch(this)->GetListOfBranches();
2084  Int_t nbranches = branches->GetEntriesFast();
2085  TBranchElement *lastbranch = this;
2086  for (Int_t i = 0; i < nbranches; ++i) {
2087  TBranchElement* subbranch = (TBranchElement*)branches->At(i);
2088  if (this!=subbranch && subbranch->fBranchClass == fBranchClass && subbranch->fCheckSum == fCheckSum) {
2089  subbranch->fOnfileObject = fOnfileObject;
2090  lastbranch = subbranch;
2091  }
2092  }
2093  lastbranch->SetBit(kOwnOnfileObj);
2094  }
2095  }
2096  fInit = kTRUE;
2097 
2098  // Get the action sequence we need to copy for reading.
2101  } else if (!fReadActionSequence) {
2102  // Get the action sequence we need to copy for reading.
2105  }
2106  SetReadLeavesPtr();
2107  SetFillLeavesPtr();
2108  }
2109 }
2110 
2111 ////////////////////////////////////////////////////////////////////////////////
2112 /// Return the collection proxy describing the branch content, if any.
2113 
2115 {
2116  if (fCollProxy) {
2117  return fCollProxy;
2118  }
2119  TBranchElement* thiscast = const_cast<TBranchElement*>(this);
2120  if (fType == 4) {
2121  // STL container top-level branch.
2122  const char* className = 0;
2123  if (fID < 0) {
2124  // We are a top-level branch.
2125  if (fBranchClass.GetClass()) {
2126  className = fBranchClass.GetClass()->GetName();
2127  }
2128  } else {
2129  // We are not a top-level branch.
2130  TVirtualStreamerInfo* si = thiscast->GetInfoImp();
2131  TStreamerElement* se = si->GetElement(fID);
2132  className = se->GetTypeName();
2133  }
2134  TClass* cl = className ? TClass::GetClass(className) : 0;
2135  if (!cl) {
2136  // The TClass was not created but we do know (since it
2137  // is used as a collection) that it 'className' was a
2138  // class, so let's create it by hand!.
2139 
2140  if (fID < 0) {
2143  className = cl->GetName();
2144  } else {
2145  cl = new TClass(className, fClassVersion);
2147  className = cl->GetName();
2148  }
2149  }
2151  if (!proxy) {
2152  // humm, we must have an older file with a custom collection
2153  // let's try to work-around it.
2154  TString equiv;
2155  equiv.Form("vector<%s>",fClonesName.Data());
2156  TClass *clequiv = TClass::GetClass(equiv);
2157  proxy = clequiv->GetCollectionProxy();
2158  if (!proxy) {
2159  Fatal("GetCollectionProxy",
2160  "Can not create a Collection Proxy of any kind for the class \"%s\" needed by the branch \"%s\" of the TTree \"%s\"!",
2161  className, GetName(), GetTree()->GetName());
2162  }
2163  if (gDebug > 0) Info("GetCollectionProxy",
2164  "Fixing the collection proxy of the class \"%s\" \n"
2165  "\tneeded by the branch \"%s\" of the TTree \"%s\" to be similar to \"%s\".",
2166  className, GetName(), GetTree()->GetName(),equiv.Data());
2167  cl->CopyCollectionProxy( *proxy );
2168  }
2169  fCollProxy = proxy->Generate();
2170  fSTLtype = proxy->GetCollectionType();
2171  } else if (fType == 41) {
2172  // STL container sub-branch.
2174  }
2175  return fCollProxy;
2176 }
2177 
2178 ////////////////////////////////////////////////////////////////////////////////
2179 /// Return a pointer to the current type of the data member corresponding to branch element.
2180 
2182 {
2183  TClass* cl = fCurrentClass;
2184  if (cl) {
2185  return cl;
2186  }
2187 
2188  TStreamerInfo* brInfo = (TStreamerInfo*)GetInfoImp();
2189  if (!brInfo) {
2191  R__ASSERT(cl && cl->GetCollectionProxy());
2192  fCurrentClass = cl;
2193  return cl;
2194  }
2195  TClass* motherCl = brInfo->GetClass();
2196  if (motherCl->GetCollectionProxy()) {
2197  cl = motherCl->GetCollectionProxy()->GetCollectionClass();
2198  if (cl) {
2199  fCurrentClass = cl;
2200  }
2201  return cl;
2202  }
2203  if (GetID() < 0 || GetID()>=brInfo->GetNelement()) {
2204  return 0;
2205  }
2206  TStreamerElement* currentStreamerElement = brInfo->GetElement(GetID());
2207  TDataMember* dm = (TDataMember*) motherCl->GetListOfDataMembers()->FindObject(currentStreamerElement->GetName());
2208 
2209  TString newType;
2210  if (!dm) {
2211  // Either the class is not loaded or the data member is gone
2212  if (!motherCl->IsLoaded()) {
2213  TVirtualStreamerInfo* newInfo = motherCl->GetStreamerInfo();
2214  if (newInfo != brInfo) {
2215  TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(currentStreamerElement->GetName());
2216  if (newElems) {
2217  if (newElems->GetClassPointer())
2218  newType = newElems->GetClassPointer()->GetName();
2219  else
2220  newType = newElems->GetTypeName();
2221  }
2222  }
2223  if (newType.Length()==0) {
2224  if (currentStreamerElement->GetClassPointer())
2225  newType = currentStreamerElement->GetClassPointer()->GetName();
2226  else
2227  newType = currentStreamerElement->GetTypeName();
2228  }
2229  }
2230  } else {
2231  newType = dm->GetTypeName();
2232  }
2233  cl = TClass::GetClass(newType);
2234  if (cl) {
2235  fCurrentClass = cl;
2236  }
2237  return cl;
2238 }
2239 
2240 ////////////////////////////////////////////////////////////////////////////////
2241 /// Read all branches of a BranchElement and return total number of bytes.
2242 ///
2243 /// - If entry = 0, then use current entry number + 1.
2244 /// - If entry < 0, then reset entry number to 0.
2245 ///
2246 /// Returns the number of bytes read from the input buffer.
2247 /// - If entry does not exist, then returns 0.
2248 /// - If an I/O error occurs, then returns -1.
2249 ///
2250 /// See IMPORTANT REMARKS in TTree::GetEntry.
2251 
2253 {
2254  // Remember which entry we are reading.
2255  fReadEntry = entry;
2256 
2257  // If our tree has a branch ref, make it remember the entry and
2258  // this branch. This allows a TRef::GetObject() call done during
2259  // the following I/O operation, for example in a custom streamer,
2260  // to search for the referenced object in the proper element of the
2261  // proper branch.
2262  TBranchRef* bref = fTree->GetBranchRef();
2263  if (R__unlikely(bref)) {
2264  R__LOCKGUARD_IMT2(gROOTMutex); // Lock for parallel TTree I/O
2265  fBranchID = bref->SetParent(this, fBranchID);
2266  bref->SetRequestedEntry(entry);
2267  }
2268 
2269  Int_t nbytes = 0;
2270 
2271  if (R__unlikely(IsAutoDelete())) {
2274  } else {
2275  if (R__unlikely(!fAddress && !fTree->GetMakeClass())) {
2276  R__LOCKGUARD_IMT2(gROOTMutex); // Lock for parallel TTree I/O
2278  }
2279  }
2280 
2281  Int_t nbranches = fBranches.GetEntriesFast();
2282  if (nbranches) {
2283  // -- Branch has daughters.
2284  // One must always read the branch counter.
2285  // In the case when one reads consecutively twice the same entry,
2286  // the user may have cleared the TClonesArray between the GetEntry calls.
2287  if ((fType == 3) || (fType == 4)) {
2288  Int_t nb = TBranch::GetEntry(entry, getall);
2289  if (nb < 0) {
2290  return nb;
2291  }
2292  nbytes += nb;
2293  }
2294  switch(fSTLtype) {
2295  case ROOT::kSTLset:
2296  case ROOT::kSTLmultiset:
2299  case ROOT::kSTLmap:
2300  case ROOT::kSTLmultimap:
2303  break;
2304  default:
2305  ValidateAddress(); // There is no ReadLeave for this node, so we need to do the validation here.
2306  for (Int_t i = 0; i < nbranches; ++i) {
2307  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
2308  Int_t nb = branch->GetEntry(entry, getall);
2309  if (nb < 0) {
2310  return nb;
2311  }
2312  nbytes += nb;
2313  }
2314  break;
2315  }
2316  } else {
2317  // -- Terminal branch.
2318  if (fBranchCount && (fBranchCount->GetReadEntry() != entry)) {
2319  Int_t nb = fBranchCount->TBranch::GetEntry(entry, getall);
2320  if (nb < 0) {
2321  return nb;
2322  }
2323  nbytes += nb;
2324  }
2325  Int_t nb = TBranch::GetEntry(entry, getall);
2326  if (nb < 0) {
2327  return nb;
2328  }
2329  nbytes += nb;
2330  }
2331 
2332  if (R__unlikely(fTree->Debug() > 0)) {
2333  if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
2334  Info("GetEntry", "%lld, branch=%s, nbytes=%d", entry, GetName(), nbytes);
2335  }
2336  }
2337  return nbytes;
2338 }
2339 
2340 ////////////////////////////////////////////////////////////////////////////////
2341 /// Fill expectedClass and expectedType with information on the data type of the
2342 /// object/values contained in this branch (and thus the type of pointers
2343 /// expected to be passed to Set[Branch]Address
2344 /// return 0 in case of success and > 0 in case of failure.
2345 
2347 {
2348  expectedClass = 0;
2349  expectedType = kOther_t;
2350 
2352  if ((type == -1) || (fID == -1)) {
2353  expectedClass = fBranchClass;
2354  } else {
2355  // Case of an object data member. Here we allow for the
2356  // variable name to be ommitted. Eg, for Event.root with split
2357  // level 1 or above Draw("GetXaxis") is the same as Draw("fH.GetXaxis()")
2358  TStreamerElement* element = GetInfoImp()->GetElement(fID);
2359  if (element) {
2360  expectedClass = element->GetClassPointer();
2361  if (!expectedClass) {
2362  TDataType* data = gROOT->GetType(element->GetTypeNameBasic());
2363  if (!data) {
2364  Error("GetExpectedType", "Did not find the type number for %s", element->GetTypeNameBasic());
2365  return 1;
2366  } else {
2367  expectedType = (EDataType) data->GetType();
2368  }
2369  }
2370  } else {
2371  Error("GetExpectedType", "Did not find the type for %s",GetName());
2372  return 2;
2373  }
2374  }
2375  return 0;
2376 }
2377 
2378 ////////////////////////////////////////////////////////////////////////////////
2379 /// Return icon name depending on type of branch element.
2380 
2381 const char* TBranchElement::GetIconName() const
2382 {
2383  if (IsFolder()) {
2384  return "TBranchElement-folder";
2385  } else {
2386  return "TBranchElement-leaf";
2387  }
2388 }
2389 
2390 ////////////////////////////////////////////////////////////////////////////////
2391 /// Return whether this branch is in a mode where the object are decomposed
2392 /// or not (Also known as MakeClass mode).
2393 
2395 {
2396  return TestBit(kDecomposedObj); // Same as TestBit(kMakeClass)
2397 }
2398 
2399 ////////////////////////////////////////////////////////////////////////////////
2400 /// Return maximum count value of the branchcount if any.
2401 
2403 {
2404  if (fBranchCount) {
2405  return fBranchCount->GetMaximum();
2406  }
2407  return fMaximum;
2408 }
2409 
2410 ////////////////////////////////////////////////////////////////////////////////
2411 /// Return a pointer to our object.
2412 
2414 {
2415  ValidateAddress();
2416  return fObject;
2417 }
2418 
2419 ////////////////////////////////////////////////////////////////////////////////
2420 /// Return a pointer to the parent class of the branch element.
2421 
2423 {
2424  return fParentClass.GetClass();
2425 }
2426 
2427 ////////////////////////////////////////////////////////////////////////////////
2428 /// Return type name of element in the branch.
2429 
2430 const char* TBranchElement::GetTypeName() const
2431 {
2432  if (fType == 3 || fType == 4) {
2433  return "Int_t";
2434  }
2435  // FIXME: Use symbolic constants here.
2436  if ((fStreamerType < 1) || (fStreamerType > 59)) {
2437  if (fBranchClass.GetClass()) {
2438  if (fID>=0) {
2439  return GetInfoImp()->GetElement(fID)->GetTypeName();
2440  } else {
2441  return fBranchClass.GetClass()->GetName();
2442  }
2443  } else {
2444  return 0;
2445  }
2446  }
2447  const char *types[20] = {
2448  "",
2449  "Char_t",
2450  "Short_t",
2451  "Int_t",
2452  "Long_t",
2453  "Float_t",
2454  "Int_t",
2455  "char*",
2456  "Double_t",
2457  "Double32_t",
2458  "",
2459  "UChar_t",
2460  "UShort_t",
2461  "UInt_t",
2462  "ULong_t",
2463  "UInt_t",
2464  "Long64_t",
2465  "ULong64_t",
2466  "Bool_t",
2467  "Float16_t"
2468  };
2469  Int_t itype = fStreamerType % 20;
2470  return types[itype];
2471 }
2472 
2473 ////////////////////////////////////////////////////////////////////////////////
2474 
2475 template Double_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2476 template Long64_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2477 template LongDouble_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2478 
2479 template <typename T>
2481 {
2482  // -- Returns the branch value.
2483  //
2484  // If the leaf is an array, j is the index in the array.
2485  //
2486  // If leaf is an array inside a TClonesArray, len should be the length
2487  // of the array.
2488  //
2489  // If subarr is true, then len is actually the index within the sub-array.
2490  //
2491 
2492  ValidateAddress();
2493 
2494  Int_t prID = fID;
2495  char *object = fObject;
2496  if (TestBit(kCache)) {
2497  if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
2498  prID = fID+1;
2499  } else if (fOnfileObject) {
2500  object = fOnfileObject->GetObjectAt(0);
2501  }
2502  }
2503 
2504  if (!j && fBranchCount) {
2505  Long64_t entry = fTree->GetReadEntry();
2506  // Since reloading the index, will reset the ClonesArray, let's
2507  // skip the load if we already read this entry.
2508  if (entry != fBranchCount->GetReadEntry()) {
2509  fBranchCount->TBranch::GetEntry(entry);
2510  }
2511  if (fBranchCount2 && entry != fBranchCount2->GetReadEntry()) {
2512  fBranchCount2->TBranch::GetEntry(entry);
2513  }
2514  }
2515 
2516  if (fTree->GetMakeClass()) {
2517  if (!fAddress) {
2518  return 0;
2519  }
2520  if ((fType == 3) || (fType == 4)) {
2521  // Top-level branch of a TClonesArray.
2522  return fNdata;
2523  } else if ((fType == 31) || (fType == 41)) {
2524  // sub branch of a TClonesArray
2525  Int_t atype = fStreamerType;
2526  if (atype < 20) {
2527  atype += 20;
2528  }
2529  return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
2530  } else if (fType <= 2) {
2531  // branch in split mode
2532  // FIXME: This should probably be < 60 instead!
2533  if ((fStreamerType > 40) && (fStreamerType < 55)) {
2534  Int_t atype = fStreamerType - 20;
2535  return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
2536  } else {
2537  return GetInfoImp()->GetTypedValue<T>(object, prID, j, -1);
2538  }
2539  }
2540  }
2541 
2542  if (object == 0)
2543  {
2544  // We have nowhere to read the data from (probably because the data member was
2545  // 'dropped' from the current schema).
2546  return 0;
2547  }
2548 
2549  if (fType == 31) {
2550  TClonesArray* clones = (TClonesArray*) object;
2551  if (subarr) {
2552  return GetInfoImp()->GetTypedValueClones<T>(clones, prID, j, len, fOffset);
2553  }
2554  return GetInfoImp()->GetTypedValueClones<T>(clones, prID, j/len, j%len, fOffset);
2555  } else if (fType == 41) {
2558  {
2559  if (subarr)
2560  return GetInfoImp()->GetTypedValueSTL<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
2561 
2562  return GetInfoImp()->GetTypedValueSTL<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
2563  }
2564  else
2565  {
2566  if (subarr)
2567  return GetInfoImp()->GetTypedValueSTLP<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
2568  return GetInfoImp()->GetTypedValueSTLP<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
2569  }
2570  } else {
2571  if (GetInfoImp()) {
2572  return GetInfoImp()->GetTypedValue<T>(object, prID, j, -1);
2573  }
2574  return 0;
2575  }
2576 }
2577 
2578 ////////////////////////////////////////////////////////////////////////////////
2579 /// Returns pointer to first data element of this branch.
2580 /// Currently used only for members of type character.
2581 
2583 {
2584  ValidateAddress();
2585 
2586  Int_t prID = fID;
2587  char *object = fObject;
2588  if (TestBit(kCache)) {
2589  if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
2590  prID = fID+1;
2591  } else if (fOnfileObject) {
2592  object = fOnfileObject->GetObjectAt(0);
2593  }
2594  }
2595 
2596  if (fBranchCount) {
2597  Long64_t entry = fTree->GetReadEntry();
2598  fBranchCount->TBranch::GetEntry(entry);
2599  if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
2600  }
2601  if (fTree->GetMakeClass()) {
2602  if (!fAddress) {
2603  return 0;
2604  }
2605  if (fType == 3) { //top level branch of a TClonesArray
2606  //return &fNdata;
2607  return 0;
2608  } else if (fType == 4) { //top level branch of a TClonesArray
2609  //return &fNdata;
2610  return 0;
2611  } else if (fType == 31) { // sub branch of a TClonesArray
2612  //Int_t atype = fStreamerType;
2613  //if (atype < 20) atype += 20;
2614  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2615  return 0;
2616  } else if (fType == 41) { // sub branch of a TClonesArray
2617  //Int_t atype = fStreamerType;
2618  //if (atype < 20) atype += 20;
2619  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2620  return 0;
2621  } else if (fType <= 2) { // branch in split mode
2622  // FIXME: This should probably be < 60 instead!
2623  if (fStreamerType > 40 && fStreamerType < 55) {
2624  //Int_t atype = fStreamerType - 20;
2625  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2626  return 0;
2627  } else {
2628  //return GetInfoImp()->GetValue(object, fID, j, -1);
2629  return 0;
2630  }
2631  }
2632  }
2633 
2634  if (fType == 31) {
2635  return 0;
2636  } else if (fType == 41) {
2637  return 0;
2638  } else if (prID < 0) {
2639  return object;
2640  } else {
2641  //return GetInfoImp()->GetValue(object,fID,j,-1);
2642  if (!GetInfoImp() || !object) return 0;
2643  char **val = (char**)(object+GetInfoImp()->TStreamerInfo::GetElementOffset(prID));
2644  return *val;
2645  }
2646 }
2647 
2648 ////////////////////////////////////////////////////////////////////////////////
2649 /// Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a container sub-branch.
2650 ///
2651 /// Note: The offsets are zero for data members so that when
2652 /// SetAddress recursively sets their address, they will get the
2653 /// same address as their containing class because i/o is based
2654 /// on streamer info offsets from the addresss of the containing
2655 /// class.
2656 ///
2657 /// Offsets are non-zero for base-class sub-branches that are
2658 /// not the leftmost direct base class. They are laid out in
2659 /// memory sequentially and only the leftmost direct base class
2660 /// has the same address as the derived class. The streamer
2661 /// offsets need to be added to the address of the base class
2662 /// subobject which is not the same as the address of the
2663 /// derived class for the non-leftmost direct base classes.
2664 
2666 {
2667  Int_t nbranches = fBranches.GetEntriesFast();
2668 
2669  if (fID < 0) {
2670  // -- We are a top-level branch. Let's mark whether we need to use MapObject.
2671  if (CanSelfReference(fBranchClass)) {
2672  if (fBranchClass.GetClass()->IsTObject()) {
2674  } else {
2675  SetBit(kBranchAny);
2676  }
2677  }
2678  }
2679  if (nbranches) {
2680  // Allocate space for the new sub-branch offsets.
2681  delete[] fBranchOffset;
2682  fBranchOffset = 0;
2683  fBranchOffset = new Int_t[nbranches];
2684  // Make sure we can instantiate our class meta info.
2685  if (!fBranchClass.GetClass()) {
2686  Warning("InitializeOffsets", "No branch class set for branch: %s", GetName());
2687  fInitOffsets = kTRUE;
2688  return;
2689  }
2690  // Make sure we can instantiate our class streamer info.
2691  if (!GetInfoImp()) {
2692  Warning("InitializeOffsets", "No streamer info available for branch: %s of class: %s", GetName(), fBranchClass.GetClass()->GetName());
2693  fInitOffsets = kTRUE;
2694  return;
2695  }
2696 
2697  // Get the class we are a member of now (which is the
2698  // type of our containing subobject) and get our offset
2699  // inside of our containing subobject (our local offset).
2700  // Note: branchElem stays zero if we are a top-level branch,
2701  // we have to be careful about this later.
2702  TStreamerElement* branchElem = 0;
2703  Int_t localOffset = 0;
2704  TClass* branchClass = fBranchClass.GetClass();
2705  Bool_t renamed = kFALSE;
2706  if (fID > -1) {
2707  // -- Branch is *not* a top-level branch.
2708  // Instead of the streamer info class, we want the class of our
2709  // specific element in the streamer info. We could be a data
2710  // member of a base class or a split class, in which case our
2711  // streamer info will be for our containing sub-object, while
2712  // we are actually a different type.
2714  // Note: We tested to make sure the streamer info was available previously.
2715  if (!si->IsCompiled()) {
2716  Warning("InitializeOffsets", "Streamer info for branch: %s has no elements array!", GetName());
2717  fInitOffsets = kTRUE;
2718  return;
2719  }
2720  // FIXME: Check that fID is in range.
2721  branchElem = si->GetElement(fID);
2722  if (!branchElem) {
2723  Warning("InitializeOffsets", "Cannot get streamer element for branch: %s!", GetName());
2724  fInitOffsets = kTRUE;
2725  return;
2726  } else if (branchElem->TestBit(TStreamerElement::kRepeat)) {
2727  // If we have a repeating streamerElement, use the next
2728  // one as it actually hold the 'real' data member('s offset)
2729  if (si->GetElement(fID+1)) {
2730  branchElem = si->GetElement(fID+1);
2731  }
2732  }
2733  localOffset = branchElem->GetOffset();
2734  branchClass = branchElem->GetClassPointer();
2735  if (localOffset == TStreamerInfo::kMissing) {
2736  fObject = 0;
2737  } else {
2738  renamed = branchClass && branchElem->GetNewClass() && (branchClass != branchElem->GetNewClass());
2739  }
2740  } else {
2741  renamed = fTargetClass != fBranchClass;
2742  }
2743  if (!branchClass) {
2744  Error("InitializeOffsets", "Could not find class for branch: %s", GetName());
2745  fInitOffsets = kTRUE;
2746  return;
2747  }
2748 
2749  //------------------------------------------------------------------------
2750  // Extract the name of the STL branch in case it has been split.
2751  //////////////////////////////////////////////////////////////////////////
2752 
2753  TString stlParentName;
2754  Bool_t stlParentNameUpdated = kFALSE;
2755  if( fType == 4 )
2756  {
2757  TBranch *br = GetMother()->GetSubBranch( this );
2758  stlParentName = br->GetName();
2759  stlParentName.Strip( TString::kTrailing, '.' );
2760 
2761  // We may ourself contain the 'Mother' branch name.
2762  // To avoid code duplication, we delegate the removal
2763  // of the mother's name to the first sub-branch loop.
2764  }
2765 
2766  // Loop over our sub-branches and compute their offsets.
2767  for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
2768  bool alternateElement = false;
2769 
2770  fBranchOffset[subBranchIdx] = 0;
2771  TBranchElement* subBranch = dynamic_cast<TBranchElement*> (fBranches[subBranchIdx]);
2772  if (subBranch == 0) {
2773  // -- Skip sub-branches that are not TBranchElements.
2774  continue;
2775  }
2776 
2777  if (renamed) {
2778  if (subBranch->fBranchClass == branchClass) {
2779  if (branchElem) subBranch->SetTargetClass(branchElem->GetNewClass()->GetName());
2780  else subBranch->SetTargetClass(fTargetClass->GetName());
2781  }
2782  }
2783 
2784  TVirtualStreamerInfo* sinfo = subBranch->GetInfoImp();
2785  if (!sinfo) {
2786  Warning("InitializeOffsets", "No streamer info for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2787  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2788  continue;
2789  }
2790  if (!sinfo->IsCompiled()) {
2791  Warning("InitializeOffsets", "No elements array for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2792  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2793  continue;
2794  }
2795  // FIXME: Make sure subBranch->fID is in range.
2796  TStreamerElement* subBranchElement = sinfo->GetElement(subBranch->fID);
2797  if (!subBranchElement) {
2798  Warning("InitializeOffsets", "No streamer element for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2799  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2800  continue;
2801  } else if (subBranchElement->TestBit(TStreamerElement::kRepeat)) {
2802  // If we have a repeating streamerElement, use the next
2803  // one as it actually hold the 'real' data member('s offset)
2804  if (sinfo->GetElement(subBranch->fID+1)) {
2805  subBranchElement = sinfo->GetElement(subBranch->fID+1);
2806  }
2807  } else if (subBranchElement->TestBit(TStreamerElement::kCache)) {
2808  // We have a cached item which is not a repeated but we might still
2809  // have some Actions triggered by a rule that affect real
2810  // data member(s).
2811  if (subBranch->fReadActionSequence && subBranch->fReadActionSequence->fActions.size() > 1) {
2812  typedef TStreamerInfoActions::ActionContainer_t::iterator iterator;
2813  iterator end = subBranch->fReadActionSequence->fActions.end();
2814  for(iterator iter = subBranch->fReadActionSequence->fActions.begin();
2815  iter != end; ++iter) {
2816  TStreamerInfoActions::TConfiguration *config = iter->fConfiguration;
2817  UInt_t id = config->fElemId;
2818  TStreamerElement *e = (TStreamerElement*)config->fInfo->GetElements()->At(id);
2819  if (e && !e->TestBit(TStreamerElement::kCache)) {
2820  subBranchElement = e;
2821  alternateElement = true;
2822  break;
2823  }
2824  }
2825  }
2826  }
2827 
2828  localOffset = subBranchElement->GetOffset();
2829  if (localOffset == TStreamerInfo::kMissing) {
2830  subBranch->fObject = 0;
2831  }
2832 
2833  {
2834  Int_t streamerType = subBranchElement->GetType();
2835  if (streamerType > TStreamerInfo::kObject
2836  && subBranch->GetListOfBranches()->GetEntries()==0
2837  && CanSelfReference(subBranchElement->GetClass()))
2838  {
2839  subBranch->SetBit(kBranchAny);
2840  } else {
2841  subBranch->ResetBit(kBranchAny);
2842  }
2843  }
2844 
2845  if (subBranchElement->GetNewType()<0) {
2846  subBranch->ResetBit(kBranchAny);
2847  subBranch->ResetBit(kBranchObject);
2848  }
2849 
2850  // Note: This call is expensive, do it only once.
2851  TBranch* mother = GetMother();
2852  if (!mother) {
2853  Warning("InitializeOffsets", "Branch '%s' has no mother!", GetName());
2854  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2855  continue;
2856  }
2857  TString motherName(mother->GetName());
2858  Bool_t motherDot = kFALSE;
2859  if (motherName.Length() && strchr(motherName.Data(), '.')) {
2860  motherDot = kTRUE;
2861  }
2862  Bool_t motherDotAtEnd = kFALSE;
2863  if (motherName.Length() && (motherName[motherName.Length()-1] == '.')) {
2864  motherDotAtEnd = kTRUE;
2865  }
2866 
2867  Bool_t isBaseSubBranch = kFALSE;
2868  if ((subBranch->fType == 1) || (subBranchElement && subBranchElement->IsBase())) {
2869  // -- Base class sub-branch (1).
2870  //
2871  // Note: Our type will not be 1, even though we are
2872  // a base class branch, if we are not split (see the
2873  // constructor), or if we are an STL container master
2874  // branch and a base class branch at the same time
2875  // or an std::string.
2876  isBaseSubBranch = kTRUE;
2877  }
2878 
2879  Bool_t isContDataMember = kFALSE;
2880  if ((subBranch->fType == 31) || (subBranch->fType == 41)) {
2881  // -- Container data member sub-branch (31 or 41).
2882  isContDataMember = kTRUE;
2883  }
2884 
2885  // I am either a data member sub-branch (0), or a base class
2886  // sub-branch (1), or TClonesArray master sub-branch (3),
2887  // or an STL container master sub-branch (4), or TClonesArray
2888  // data member sub-branch (31), or an STL container data member
2889  // sub-branch (41).
2890  //
2891  // My parent branch is either a top-level branch ((0), fID==(-2,-1)),
2892  // or a base class sub-branch (1), or a split-class branch (2),
2893  // or a TClonesArray master branch (3), or an STL container
2894  // master branch (4).
2895  //
2896 
2897  //
2898  // We need to extract from our name the name
2899  // of the data member which contains us, so
2900  // that we may then do a by-name lookup in the
2901  // dictionary meta info of our parent class to
2902  // get our offset in our parent class.
2903  //
2904 
2905  // Get our name.
2906  TString dataName(subBranch->GetName());
2907  if (motherDotAtEnd) {
2908  // -- Remove the top-level branch name from our name.
2909  dataName.Remove(0, motherName.Length());
2910  // stlParentNameUpdated is false the first time in this loop.
2911  if (!stlParentNameUpdated && stlParentName.Length()) {
2912  stlParentName.Remove(0, motherName.Length());
2913  stlParentNameUpdated = kTRUE;
2914  }
2915  } else if (motherDot) {
2916  // -- Remove the top-level branch name from our name, folder case.
2917  //
2918  // Note: We are in the case where our mother was created
2919  // by the branch constructor which takes a folder
2920  // as an argument. The mother branch has internal
2921  // dots in its name to represent the folder heirarchy.
2922  // The TTree::Bronch() routine has handled us as a
2923  // special case, we must compensate.
2924  if ((fID < 0) && (subBranchElement->IsA() == TStreamerBase::Class())) {
2925  // -- Our name is the mother name, remove it.
2926  // Note: The test is our parent is a top-level branch
2927  // and our streamer is the base class streamer,
2928  // this matches the exact test in TTree::Bronch().
2929  if (dataName.Length() == motherName.Length()) {
2930  dataName.Remove(0, motherName.Length());
2931  // stlParentNameUpdated is false the first time in this loop.
2932  if (!stlParentNameUpdated && stlParentName.Length()) {
2933  stlParentName.Remove(0, motherName.Length());
2934  }
2935  }
2936  } else {
2937  // -- Remove the mother name and the dot.
2938  if (dataName.Length() > motherName.Length()) {
2939  dataName.Remove(0, motherName.Length() + 1);
2940  if (!stlParentNameUpdated && stlParentName.Length()) {
2941  stlParentName.Remove(0, motherName.Length());
2942  }
2943  }
2944  }
2945  }
2946  stlParentNameUpdated = kTRUE;
2947  if (isBaseSubBranch) {
2948  // -- Remove the base class name suffix from our name.
2949  // Note: The pattern is the name of the base class.
2950  TString pattern(subBranchElement->GetName());
2951  if (pattern.Length() <= dataName.Length()) {
2952  if (!strcmp(dataName.Data() + (dataName.Length() - pattern.Length()), pattern.Data())) {
2953  // The branch name contains the name of the base class in it.
2954  // This name is not reproduced in the sub-branches, so we need to
2955  // remove it.
2956  dataName.Remove(dataName.Length() - pattern.Length());
2957  }
2958  }
2959  // Remove any leading dot.
2960  if (dataName.Length()) {
2961  if (dataName[0] == '.') {
2962  dataName.Remove(0, 1);
2963  }
2964  }
2965  // Note: We intentionally leave any trailing dot
2966  // in our modified name here.
2967  }
2968 
2969  // Get our parent branch's name.
2970  TString parentName(GetName());
2971  if (motherDotAtEnd) {
2972  // -- Remove the top-level branch name from our parent's name.
2973  parentName.Remove(0, motherName.Length());
2974  } else if (motherDot) {
2975  // -- Remove the top-level branch name from our parent's name, folder case.
2976  //
2977  // Note: We are in the case where our mother was created
2978  // by the branch constructor which takes a folder
2979  // as an argument. The mother branch has internal
2980  // dots in its name to represent the folder heirarchy.
2981  // The TTree::Bronch() routine has handled us as a
2982  // special case, we must compensate.
2983  if ((fID > -1) && (mother == mother->GetSubBranch(this)) && (branchElem->IsA() == TStreamerBase::Class())) {
2984  // -- Our parent's name is the mother name, remove it.
2985  // Note: The test is our parent's parent is a top-level branch
2986  // and our parent's streamer is the base class streamer,
2987  // this matches the exact test in TTree::Bronch().
2988  if (parentName.Length() == motherName.Length()) {
2989  parentName.Remove(0, motherName.Length());
2990  }
2991  } else {
2992  // -- Remove the mother name and the dot.
2993  if (parentName.Length() > motherName.Length()) {
2994  parentName.Remove(0, motherName.Length() + 1);
2995  }
2996  }
2997  }
2998  // FIXME: Do we need to use the other tests for a base class here?
2999  if (fType == 1) {
3000  // -- Our parent is a base class sub-branch, remove the base class name suffix from its name.
3001  if (mother != mother->GetSubBranch(this)) {
3002  // -- My parent's parent is not a top-level branch.
3003  // Remove the base class name suffix from the parent name.
3004  // Note: The pattern is the name of the base class.
3005  // coverity[var_deref_model] branchElem is non zero here since fType==1 and thus fID > -1
3006  TString pattern(branchElem->GetName());
3007  if (pattern.Length() <= parentName.Length()) {
3008  if (!strcmp(parentName.Data() + (parentName.Length() - pattern.Length()), pattern.Data())) {
3009  // The branch name contains the name of the base class in it.
3010  // This name is not reproduced in the sub-branches, so we need to
3011  // remove it.
3012  parentName.Remove(parentName.Length() - pattern.Length());
3013  }
3014  }
3015  }
3016  // Note: We intentionally leave any trailing dots
3017  // in the modified parent name here.
3018  }
3019 
3020  // Remove the parent branch name part from our name,
3021  // but only if the parent branch is not a top-level branch.
3022  // FIXME: We should not assume parent name does not have length 0.
3023  if (fID > -1) {
3024  RemovePrefix(dataName, parentName);
3025  }
3026 
3027  // Remove any leading dot.
3028  if (dataName.Length()) {
3029  if (dataName[0] == '.') {
3030  dataName.Remove(0, 1);
3031  }
3032  }
3033 
3034  // Remove any trailing dot.
3035  if (dataName.Length()) {
3036  if (dataName[dataName.Length()-1] == '.') {
3037  dataName.Remove(dataName.Length() - 1, 1);
3038  }
3039  }
3040 
3041  //
3042  // Now that we have our data member name, find our offset
3043  // in our parent class.
3044  //
3045  // Note: Our data member name can have many dots in it
3046  // if branches were elided between our parent branch
3047  // and us by Unroll().
3048  //
3049  // FIXME: This may not work if our member name is ambiguous.
3050  //
3051 
3052  Int_t offset = 0;
3053  if (dataName.Length()) {
3054  // -- We have our data member name, do a lookup in the dictionary meta info of our parent class.
3055  // Get our parent class.
3056  TClass* pClass = 0;
3057  // First check whether this sub-branch is part of the 'cache' (because the data member it
3058  // represents is no longer in the current class layout.
3059  TStreamerInfo *subInfo = subBranch->GetInfoImp();
3060  //if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
3061  if (subBranchElement->TestBit(TStreamerElement::kCache)) {
3062  pClass = ((TStreamerElement*)subInfo->GetElements()->At(0))->GetClassPointer();
3063  }
3064  // FIXME: Do we need the other base class tests here?
3065  if (!pClass) {
3066  if (fType == 1) {
3067  // -- Parent branch is a base class branch.
3068  // FIXME: Is using branchElem here the right thing?
3069  pClass = branchElem->GetClassPointer();
3070  if (pClass->Property() & kIsAbstract) {
3071  // the class is abstract, let see if the
3072 
3073  TBranchElement *parent = (TBranchElement*)GetMother()->GetSubBranch(this);
3074  if (parent && parent != this && !parent->GetClass()->IsLoaded() ) {
3075  // Our parent's class is emulated and we represent an abstract class.
3076  // and the target class has not been set explicilty.
3077  TString target = pClass->GetName();
3078  target += "@@emulated";
3079 
3080  pClass = TClass::GetClass(target);
3081  }
3082  }
3083  } else {
3084  // -- Parent branch is *not* a base class branch.
3085  // FIXME: This sometimes returns a null pointer.
3086  pClass = subBranch->GetParentClass();
3087  }
3088  }
3089  if (!pClass) {
3090  // -- No parent class, fix it.
3091  // FIXME: This is probably wrong!
3092  // Assume parent class is our parent branch's clones class or value class.
3093  if (GetClonesName() && strlen(GetClonesName())) {
3094  pClass = fClonesClass;
3095  if (!pClass) {
3096  Warning("InitializeOffsets", "subBranch: '%s' has no parent class, and cannot get class for clones class: '%s'!", subBranch->GetName(), GetClonesName());
3097  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3098  continue;
3099  }
3100  Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3101  }
3103  pClass = fBranchCount->fCollProxy->GetValueClass();
3104  Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass ? pClass->GetName() : "unknowned class");
3105  }
3106  if (!pClass) {
3107  // -- Still no parent class, assume our parent class is our parent branch's class.
3108  // FIXME: This is probably wrong!
3109  pClass = branchClass;
3110  // FIXME: Enable this warning!
3111  //Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3112  }
3113  }
3114  if (renamed && pClass) {
3115  if (pClass == branchClass) {
3116  pClass = branchElem->GetNewClass();
3117  } else if (fCollProxy && pClass == branchClass->GetCollectionProxy()->GetValueClass()) {
3118  pClass = fCollProxy->GetValueClass();
3119  }
3120  }
3121 
3122  //------------------------------------------------------------------
3123  // If we have the are the sub-branch of the TBranchSTL, we need
3124  // to remove it's name to get the correct real data offsets
3125  ////////////////////////////////////////////////////////////////////
3126 
3127  if( dynamic_cast<TBranchSTL*>(fParent) && stlParentName.Length() )
3128  {
3129  if( !strncmp( stlParentName.Data(), dataName.Data(), stlParentName.Length()-1 )
3130  && dataName[ stlParentName.Length() ] == '.' )
3131  dataName.Remove( 0, stlParentName.Length()+1 );
3132  }
3133 
3134  // Find our offset in our parent class using
3135  // a lookup by name in the dictionary meta info
3136  // for our parent class.
3137 
3138  if (alternateElement) {
3139  Ssiz_t dotpos = dataName.Last('.');
3140  Ssiz_t endpos = dataName.Length();
3141  if (dotpos != kNPOS) ++dotpos; else dotpos = 0;
3142  dataName.Replace(dotpos,endpos-dotpos,subBranchElement->GetFullName());
3143  }
3144  TRealData* rd = pClass->GetRealData(dataName);
3145  if (rd && (!rd->TestBit(TRealData::kTransient) || alternateElement)) {
3146  // -- Data member exists in the dictionary meta info, get the offset.
3147  // If we are using an alternateElement, it is the target of a rule
3148  // and might be indeed transient.
3149  offset = rd->GetThisOffset();
3150  } else if (subBranchElement->TestBit(TStreamerElement::kWholeObject)) {
3151  // We are a rule with no specific target, it applies to the whole
3152  // object, let's set the offset to zero
3153  offset = 0;
3154  } else {
3155  // -- No dictionary meta info for this data member, it must no
3156  // longer exist
3157  if (fEntries == 0) {
3158  // ... unless we creating the branch in which case
3159  // we have an internal error.
3160  if (pClass->GetListOfRealData()->GetEntries() == 0) {
3161  // We are probably missing the ShowMember, let's
3162  // just issue an error.
3163  Error("InitializeOffsets",
3164  "Could not find the real data member '%s' when constructing the branch '%s' [Likely missing ShowMember].",
3165  dataName.Data(),GetName());
3166  } else if (subInfo && subInfo->GetClassVersion()!=subInfo->GetClass()->GetClassVersion()) {
3167  // In the case where we are cloning a TTree that was created with an older version of the layout, we may not
3168  // able to find all the members
3169  Info("InitializeOffsets",
3170  "TTree created with an older schema, some data might not be copied in 'slow-cloning' mode; fast-cloning should have the correct result. '%s' is missing when constructing the branch '%s'. ",
3171  dataName.Data(),GetName());
3172  } else {
3173  // Something really bad happen.
3174  Fatal("InitializeOffsets",
3175  "Could not find the real data member '%s' when constructing the branch '%s' [Likely an internal error, please report to the developers].",
3176  dataName.Data(),GetName());
3177  }
3178  }
3179  localOffset = TStreamerInfo::kMissing;
3180  }
3181  } else {
3182  // -- We have no data member name, ok for a base class, not good otherwise.
3183  if (isBaseSubBranch) {
3184  // I am a direct base class of my parent class, my local offset is enough.
3185  } else {
3186  Warning("InitializeOffsets", "Could not find the data member name for branch '%s' with parent branch '%s', assuming offset is zero!", subBranch->GetName(), GetName());
3187  }
3188  }
3189 
3190  //
3191  // Ok, do final calculations for fOffset and fBranchOffset.
3192  //
3193 
3194  if (isContDataMember) {
3195  // -- Container data members set fOffset instead of fBranchOffset.
3196  // The fOffset is what should be added to the start of the entry
3197  // in the collection (i.e., its current absolute address) to find
3198  // the beginning of the data member described by the current branch.
3199  //
3200  // Compensate for the i/o routines adding our local offset later.
3201  if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
3202  subBranch->SetOffset(TStreamerInfo::kMissing);
3203  // We stil need to set fBranchOffset in the case of a missing
3204  // element so that SetAddress is (as expected) not called
3205  // recursively in this case.
3206  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3207  } else {
3208  if (isBaseSubBranch) {
3209  // The value of 'offset' for a base class does not include its
3210  // 'localOffset'.
3211  subBranch->SetOffset(offset);
3212  } else {
3213  // The value of 'offset' for a regular data member does include its
3214  // 'localOffset', we need to remove it explicitly.
3215  subBranch->SetOffset(offset - localOffset);
3216  }
3217  }
3218  } else {
3219  // -- Set fBranchOffset for sub-branch.
3220  Int_t isSplit = 0 != subBranch->GetListOfBranches()->GetEntriesFast();
3221  if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
3222  // The branch is missing
3223  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3224 
3225  } else if (isSplit) {
3226  if (isBaseSubBranch) {
3227  // We are split, so we need to add in our local offset
3228  // to get our absolute address for our children.
3229  fBranchOffset[subBranchIdx] = offset + localOffset;
3230  } else {
3231  // We are split so our offset will never be
3232  // used in an i/o, so we do not have to subtract
3233  // off our local offset like below.
3234  fBranchOffset[subBranchIdx] = offset;
3235  }
3236  } else {
3237  if (isBaseSubBranch) {
3238  // We are not split, so our local offset will be
3239  // added later by the i/o routines.
3240  fBranchOffset[subBranchIdx] = offset;
3241  } else {
3242  // Compensate for the fact that the i/o routines
3243  // are going to add my local offset later.
3244  fBranchOffset[subBranchIdx] = offset - localOffset;
3245  }
3246  }
3247  }
3248  }
3249  }
3250  else {
3251  if (fID > -1) {
3252  // Branch is *not* a top-level branch.
3253  // Let's check if the target member is still present in memory
3255  fObject = 0;
3256  }
3257  }
3258  }
3259  fInitOffsets = kTRUE;
3260 }
3261 
3262 ////////////////////////////////////////////////////////////////////////////////
3263 /// Return kTRUE if more than one leaf, kFALSE otherwise.
3264 
3266 {
3267  Int_t nbranches = fBranches.GetEntriesFast();
3268  if (nbranches >= 1) {
3269  return kTRUE;
3270  }
3271  TList* browsables = const_cast<TBranchElement*>(this)->GetBrowsables();
3272  return browsables && browsables->GetSize();
3273 }
3274 
3275 ////////////////////////////////////////////////////////////////////////////////
3276 /// Detect a collection written using a zero pointer in old versions of root.
3277 /// In versions of ROOT older than 4.00/03, if a collection (TClonesArray
3278 /// or STL container) was split but the pointer to the collection was zeroed
3279 /// out, nothing was saved. Hence there is no __easy__ way to detect the
3280 /// case. In newer versions, a zero is written so that a 'missing' collection
3281 /// appears to be an empty collection.
3282 
3284 {
3285  Bool_t ismissing = kFALSE;
3287  if (basket && fTree) {
3288  Long64_t entry = fTree->GetReadEntry();
3290  Long64_t last;
3291  if (fReadBasket == fWriteBasket) {
3292  last = fEntryNumber - 1;
3293  } else {
3294  last = fBasketEntry[fReadBasket+1] - 1;
3295  }
3296  Int_t* entryOffset = basket->GetEntryOffset();
3297  Int_t bufbegin;
3298  Int_t bufnext;
3299  if (entryOffset) {
3300  bufbegin = entryOffset[entry-first];
3301 
3302  if (entry < last) {
3303  bufnext = entryOffset[entry+1-first];
3304  } else {
3305  bufnext = basket->GetLast();
3306  }
3307  if (bufnext == bufbegin) {
3308  ismissing = kTRUE;
3309  } else {
3310  // fixed length buffer so this is not the case here.
3311  if (basket->GetNevBufSize() == 0) {
3312  ismissing = kTRUE;
3313  }
3314  }
3315  }
3316  }
3317  return ismissing;
3318 }
3319 
3320 ////////////////////////////////////////////////////////////////////////////////
3321 /// Print branch parameters.
3322 
3323 void TBranchElement::Print(Option_t* option) const
3324 {
3325  Int_t nbranches = fBranches.GetEntriesFast();
3326  if (strncmp(option,"debugAddress",strlen("debugAddress"))==0) {
3327  if (strlen(option)==strlen("debugAddress")) {
3328  Printf("%-24s %-16s %2s %4s %-16s %-16s %8s %8s %s\n",
3329  "Branch Name", "Streamer Class", "ID", "Type", "Class", "Parent", "pOffset", "fOffset", "fObject");
3330  }
3331  if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
3332  else Printf("%-24s ", GetName());
3333 
3334  TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
3335  Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
3336  TVirtualStreamerInfo *info = ((TBranchElement*)this)->GetInfoImp();
3337 
3338  Printf("%-16s %2d %4d %-16s %-16s %8x %8x %s\n",
3339  info ? info->GetName() : "StreamerInfo unvailable", GetID(), GetType(),
3341  (fBranchOffset&&parent && ind>=0) ? parent->fBranchOffset[ind] : 0,
3342  GetOffset(), GetObject());
3343  for (Int_t i = 0; i < nbranches; ++i) {
3344  TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
3345  subbranch->Print("debugAddressSub");
3346  }
3347  return;
3348  }
3349  if (strncmp(option,"debugInfo",strlen("debugInfo"))==0) {
3350  Printf("Branch %s uses:",GetName());
3351  if (fID>=0) {
3352  GetInfoImp()->GetElement(fID)->ls();
3353  for(UInt_t i=0; i< fIDs.size(); ++i) {
3354  GetInfoImp()->GetElement(fIDs[i])->ls();
3355  }
3356  Printf(" with read actions:");
3358  Printf(" with write actions:");
3360  }
3361  TString suboption = "debugInfoSub";
3362  suboption += (option+strlen("debugInfo"));
3363  for (Int_t i = 0; i < nbranches; ++i) {
3364  TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
3365  subbranch->Print(suboption);
3366  }
3367  Printf(" ");
3368  return;
3369  }
3370  if (nbranches) {
3371  if (fID == -2) {
3372  if (strcmp(GetName(),GetTitle()) == 0) {
3373  Printf("*Branch :%-66s *",GetName());
3374  } else {
3375  Printf("*Branch :%-9s : %-54s *",GetName(),GetTitle());
3376  }
3377  Printf("*Entries : %8d : BranchElement (see below) *",Int_t(fEntries));
3378  Printf("*............................................................................*");
3379  }
3380  if (fType >= 2) {
3381  TBranch::Print(option);
3382  }
3383  for (Int_t i=0;i<nbranches;i++) {
3384  TBranch *branch = (TBranch*)fBranches.At(i);
3385  branch->Print(option);
3386  }
3387  } else {
3388  TBranch::Print(option);
3389  }
3390 }
3391 
3392 ////////////////////////////////////////////////////////////////////////////////
3393 /// Prints values of leaves.
3394 
3396 {
3397  ValidateAddress();
3398 
3399  TStreamerInfo *info = GetInfoImp();
3400  Int_t prID = fID;
3401  char *object = fObject;
3402  if (TestBit(kCache)) {
3404  prID = fID+1;
3405  } else if (fOnfileObject) {
3406  object = fOnfileObject->GetObjectAt(0);
3407  }
3408  }
3409 
3410  if (fTree->GetMakeClass()) {
3411  if (!fAddress) {
3412  return;
3413  }
3414  if (fType == 3 || fType == 4) {
3415  // TClonesArray or STL container top-level branch.
3416  printf(" %-15s = %d\n", GetName(), fNdata);
3417  return;
3418  } else if (fType == 31 || fType == 41) {
3419  // TClonesArray or STL container sub-branch.
3420  Int_t n = TMath::Min(10, fNdata);
3423  // TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar is
3424  // printed as a string and could print weird characters.
3425  // So we print an unsigned char instead (not perfect, but better).
3426  atype = TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar;
3427  }
3428  if (atype > 54) {
3429  // FIXME: More logic required here (like in ReadLeaves)
3430  printf(" %-15s = %d\n", GetName(), fNdata);
3431  return;
3432  }
3433  if (fStreamerType > 20) {
3434  atype -= 20;
3436  n = n * leaf->GetLenStatic();
3437  }
3438  if (GetInfoImp()) {
3439  GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
3440  }
3441  return;
3442  } else if (fType <= 2) {
3443  // Branch in split mode.
3444  // FIXME: This should probably be < 60 instead.
3445  if ((fStreamerType > 40) && (fStreamerType < 55)) {
3446  Int_t atype = fStreamerType - 20;
3447  TBranchElement* counterElement = (TBranchElement*) fBranchCount;
3448  Int_t n = (Int_t) counterElement->GetValue(0, 0);
3449  if (GetInfoImp()) {
3450  GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
3451  }
3452  } else {
3453  if (GetInfoImp()) {
3454  GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
3455  }
3456  }
3457  return;
3458  }
3459  } else if (fType == 3) {
3460  printf(" %-15s = %d\n", GetName(), fNdata);
3461  } else if (fType == 31) {
3462  TClonesArray* clones = (TClonesArray*) object;
3463  if (GetInfoImp()) {
3464  GetInfoImp()->PrintValueClones(GetName(), clones, prID, fOffset, lenmax);
3465  }
3466  } else if (fType == 41) {
3468  if (GetInfoImp()) {
3469  GetInfoImp()->PrintValueSTL(GetName(), ((TBranchElement*) this)->GetCollectionProxy(), prID, fOffset, lenmax);
3470  }
3471  } else {
3472  if (GetInfoImp()) {
3473  GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
3474  }
3475  }
3476 }
3477 
3478 ////////////////////////////////////////////////////////////////////////////////
3479 /// Unconfiguration Read Leave function.
3480 
3482 {
3483  Fatal("ReadLeaves","The ReadLeaves function has not been configured for %s",GetName());
3484 }
3485 
3486 ////////////////////////////////////////////////////////////////////////////////
3487 /// Read leaves into i/o buffers for this branch.
3488 /// For the case where the branch is set in MakeClass mode (decomposed object).
3489 
3491 {
3492  ValidateAddress();
3493 
3494  if (fType == 3 || fType == 4) {
3495  // Top level branch of a TClonesArray.
3496  Int_t *n = (Int_t*) fAddress;
3497  b >> n[0];
3498  if ((n[0] < 0) || (n[0] > fMaximum)) {
3499  if (IsMissingCollection()) {
3500  n[0] = 0;
3501  b.SetBufferOffset(b.Length() - sizeof(n));
3502  } else {
3503  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());
3504  n[0] = 0;
3505  }
3506  }
3507  fNdata = n[0];
3508  if (fType == 4) {
3509  Int_t nbranches = fBranches.GetEntriesFast();
3510  switch(fSTLtype) {
3511  case ROOT::kSTLset:
3512  case ROOT::kSTLmultiset:
3513  case ROOT::kSTLmap:
3514  case ROOT::kSTLmultimap:
3515  for (Int_t i=0; i<nbranches; i++) {
3516  TBranch *branch = (TBranch*)fBranches[i];
3517  Int_t nb = branch->GetEntry(GetReadEntry(), 1);
3518  if (nb < 0) {
3519  break;
3520  }
3521  }
3522  break;
3523  default:
3524  break;
3525  }
3526  }
3527  return;
3528  } else if (fType == 31 || fType == 41) { // sub branch of a TClonesArray
3530  Int_t atype = fStreamerType;
3531  // FIXME: This should probably be > 59 instead.
3532  if (atype > 54) return;
3533  if (!fAddress) {
3534  return;
3535  }
3536  Int_t n = fNdata;
3537  if (atype>40) {
3538  atype -= 40;
3539  if (!fBranchCount2) return;
3540  const char *len_where = (char*)fBranchCount2->fAddress;
3541  if (!len_where) return;
3542  Int_t len_atype = fBranchCount2->fStreamerType;
3543  Int_t length;
3544  Int_t k;
3545  Char_t isArray;
3546  for( k=0; k<n; k++) {
3547  char **where = &(((char**)fAddress)[k]);
3548  delete [] *where;
3549  *where = 0;
3550  switch(len_atype) {
3551  case 1: {length = ((Char_t*) len_where)[k]; break;}
3552  case 2: {length = ((Short_t*) len_where)[k]; break;}
3553  case 3: {length = ((Int_t*) len_where)[k]; break;}
3554  case 4: {length = ((Long_t*) len_where)[k]; break;}
3555  //case 5: {length = ((Float_t*) len_where)[k]; break;}
3556  case 6: {length = ((Int_t*) len_where)[k]; break;}
3557  //case 8: {length = ((Double_t*)len_where)[k]; break;}
3558  case 11: {length = ((UChar_t*) len_where)[k]; break;}
3559  case 12: {length = ((UShort_t*) len_where)[k]; break;}
3560  case 13: {length = ((UInt_t*) len_where)[k]; break;}
3561  case 14: {length = ((ULong_t*) len_where)[k]; break;}
3562  case 15: {length = ((UInt_t*) len_where)[k]; break;}
3563  case 16: {length = ((Long64_t*) len_where)[k]; break;}
3564  case 17: {length = ((ULong64_t*)len_where)[k]; break;}
3565  case 18: {length = ((Bool_t*) len_where)[k]; break;}
3566  default: continue;
3567  }
3568  b >> isArray;
3569  if (length <= 0) continue;
3570  if (isArray == 0) continue;
3571  switch (atype) {
3572  case 1: {*where=new char[sizeof(Char_t)*length]; b.ReadFastArray((Char_t*) *where, length); break;}
3573  case 2: {*where=new char[sizeof(Short_t)*length]; b.ReadFastArray((Short_t*) *where, length); break;}
3574  case 3: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*) *where, length); break;}
3575  case 4: {*where=new char[sizeof(Long_t)*length]; b.ReadFastArray((Long_t*) *where, length); break;}
3576  case 5: {*where=new char[sizeof(Float_t)*length]; b.ReadFastArray((Float_t*) *where, length); break;}
3577  case 6: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*) *where, length); break;}
3578  case 8: {*where=new char[sizeof(Double_t)*length]; b.ReadFastArray((Double_t*)*where, length); break;}
3579  case 11: {*where=new char[sizeof(UChar_t)*length]; b.ReadFastArray((UChar_t*) *where, length); break;}
3580  case 12: {*where=new char[sizeof(UShort_t)*length]; b.ReadFastArray((UShort_t*)*where, length); break;}
3581  case 13: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*) *where, length); break;}
3582  case 14: {*where=new char[sizeof(ULong_t)*length]; b.ReadFastArray((ULong_t*) *where, length); break;}
3583  case 15: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*) *where, length); break;}
3584  case 16: {*where=new char[sizeof(Long64_t)*length]; b.ReadFastArray((Long64_t*) *where, length); break;}
3585  case 17: {*where=new char[sizeof(ULong64_t)*length]; b.ReadFastArray((ULong64_t*)*where, length); break;}
3586  case 18: {*where=new char[sizeof(Bool_t)*length]; b.ReadFastArray((Bool_t*) *where, length); break;}
3587  }
3588  }
3589  return;
3590  }
3591  if (atype > 20) {
3592  atype -= 20;
3594  n *= leaf->GetLenStatic();
3595  }
3596  switch (atype) {
3597  case 1: {b.ReadFastArray((Char_t*) fAddress, n); break;}
3598  case 2: {b.ReadFastArray((Short_t*) fAddress, n); break;}
3599  case 3: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3600  case 4: {b.ReadFastArray((Long_t*) fAddress, n); break;}
3601  case 5: {b.ReadFastArray((Float_t*) fAddress, n); break;}
3602  case 6: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3603  case 8: {b.ReadFastArray((Double_t*)fAddress, n); break;}
3604  case 11: {b.ReadFastArray((UChar_t*) fAddress, n); break;}
3605  case 12: {b.ReadFastArray((UShort_t*)fAddress, n); break;}
3606  case 13: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3607  case 14: {b.ReadFastArray((ULong_t*) fAddress, n); break;}
3608  case 15: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3609  case 16: {b.ReadFastArray((Long64_t*)fAddress, n); break;}
3610  case 17: {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
3611  case 18: {b.ReadFastArray((Bool_t*) fAddress, n); break;}
3612  case 9: {
3615  Double_t *xx = (Double_t*) fAddress;
3616  for (Int_t ii=0;ii<n;ii++) {
3617  b.ReadDouble32(&(xx[ii]),se);
3618  }
3619  break;
3620  }
3621  case 19: {
3624  Float_t *xx = (Float_t*) fAddress;
3625  for (Int_t ii=0;ii<n;ii++) {
3626  b.ReadFloat16(&(xx[ii]),se);
3627  }
3628  break;
3629  }
3630  }
3631  return;
3632  } else if (fType <= 2) { // branch in split mode
3633  // FIXME: This should probably be < 60 instead.
3634  if (fStreamerType > 40 && fStreamerType < 55) {
3635  Int_t atype = fStreamerType - 40;
3636  Int_t n;
3637  if (fBranchCount==0) {
3638  // Missing fBranchCount. let's attempts to recover.
3639 
3640  TString countname( GetName() );
3641  Ssiz_t dot = countname.Last('.');
3642  if (dot>=0) {
3643  countname.Remove(dot+1);
3644  } else {
3645  countname = "";
3646  }
3647  TString counter( GetTitle() );
3648  Ssiz_t loc = counter.Last('[');
3649  if (loc>=0) {
3650  counter.Remove(0,loc+1);
3651  }
3652  loc = counter.Last(']');
3653  if (loc>=0) {
3654  counter.Remove(loc);
3655  }
3656  countname += counter;
3657  SetBranchCount((TBranchElement *)fTree->GetBranch(countname));
3658  }
3659  if (fBranchCount) {
3660  n = (Int_t)fBranchCount->GetValue(0,0);
3661  } else {
3662  Warning("ReadLeaves","Missing fBranchCount for %s. Data will not be read correctly by the MakeClass mode.",GetName());
3663  n = 0;
3664  }
3665  fNdata = n;
3666  Char_t isArray;
3667  b >> isArray;
3668  switch (atype) {
3669  case 1: {b.ReadFastArray((Char_t*) fAddress, n); break;}
3670  case 2: {b.ReadFastArray((Short_t*) fAddress, n); break;}
3671  case 3: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3672  case 4: {b.ReadFastArray((Long_t*) fAddress, n); break;}
3673  case 5: {b.ReadFastArray((Float_t*) fAddress, n); break;}
3674  case 6: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3675  case 8: {b.ReadFastArray((Double_t*)fAddress, n); break;}
3676  case 11: {b.ReadFastArray((UChar_t*) fAddress, n); break;}
3677  case 12: {b.ReadFastArray((UShort_t*)fAddress, n); break;}
3678  case 13: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3679  case 14: {b.ReadFastArray((ULong_t*) fAddress, n); break;}
3680  case 15: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3681  case 16: {b.ReadFastArray((Long64_t*) fAddress, n); break;}
3682  case 17: {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
3683  case 18: {b.ReadFastArray((Bool_t*) fAddress, n); break;}
3684  case 9: {
3687  Double_t *xx = (Double_t*) fAddress;
3688  for (Int_t ii=0;ii<n;ii++) {
3689  b.ReadDouble32(&(xx[ii]),se);
3690  }
3691  break;
3692  }
3693  case 19: {
3696  Float_t *xx = (Float_t*) fAddress;
3697  for (Int_t ii=0;ii<n;ii++) {
3698  b.ReadFloat16(&(xx[ii]),se);
3699  }
3700  break;
3701  }
3702  }
3703  } else {
3704  fNdata = 1;
3705  if (fAddress) {
3706  if (fType<0) {
3707  // Non TObject, Non collection classes with a custom streamer.
3708 
3709  // if (fObject)
3711  } else {
3712  TStreamerInfo *info = GetInfoImp();
3713  if (!info) {
3714  return;
3715  }
3716  // Since info is not null, fReadActionSequence is not null either.
3718  }
3720  fNdata = (Int_t) GetValue(0, 0);
3721  }
3722  } else {
3723  fNdata = 0;
3724  }
3725  }
3726  return;
3727  }
3728 }
3729 
3730 ////////////////////////////////////////////////////////////////////////////////
3731 /// Read leaves into i/o buffers for this branch.
3732 /// Case of a collection (fType == 4).
3733 
3735 {
3736  ValidateAddress();
3737  if (fObject == 0)
3738  {
3739  // We have nowhere to copy the data (probably because the data member was
3740  // 'dropped' from the current schema) so let's no copy it in a random place.
3741  return;
3742  }
3743 
3744  // STL container master branch (has only the number of elements).
3745  Int_t n;
3746  b >> n;
3747  if ((n < 0) || (n > fMaximum)) {
3748  if (IsMissingCollection()) {
3749  n = 0;
3750  b.SetBufferOffset(b.Length()-sizeof(n));
3751  } else {
3752  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());
3753  n = 0;
3754  }
3755  }
3756  fNdata = n;
3757 
3758  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,n);
3759 
3760  // Note: Proxy-helper needs to "embrace" the entire
3761  // streaming of this STL container if the container
3762  // is a set/multiset/map/multimap (what we do not
3763  // know here).
3764  // For vector/list/deque Allocate == Resize
3765  // and Commit == noop.
3766  // TODO: Exception safety a la TPushPop
3769  void* alternate = proxy->Allocate(fNdata, true);
3771  fPtrIterators->CreateIterators(alternate, proxy);
3772  } else {
3773  fIterators->CreateIterators(alternate, proxy);
3774  }
3775 
3776  Int_t nbranches = fBranches.GetEntriesFast();
3777  switch (fSTLtype) {
3778  case ROOT::kSTLset:
3781  case ROOT::kSTLmultiset:
3782  case ROOT::kSTLmap:
3783  case ROOT::kSTLmultimap:
3786  for (Int_t i = 0; i < nbranches; ++i) {
3787  TBranch *branch = (TBranch*) fBranches[i];
3788  Int_t nb = branch->GetEntry(GetReadEntry(), 1);
3789  if (nb < 0) {
3790  // Give up on i/o failure.
3791  // FIXME: We need an error message here.
3792  break;
3793  }
3794  }
3795  break;
3796  default:
3797  break;
3798  }
3799  //------------------------------------------------------------------------
3800  // We have split this stuff, so we need to create the the pointers
3801  /////////////////////////////////////////////////////////////////////////////
3802 
3804  {
3805  TClass *elClass = proxy->GetValueClass();
3806 
3807  //--------------------------------------------------------------------
3808  // The allocation is done in this strange way because ReadLeaves
3809  // is being called many times by TTreeFormula!!!
3810  //////////////////////////////////////////////////////////////////////////
3811 
3812  Int_t i = 0;
3813  // coverity[returned_null] the fNdata is check enough to prevent the use of null value of At(0)
3814  if( !fNdata || *(void**)proxy->At( 0 ) != 0 )
3815  i = fNdata;
3816 
3817  for( ; i < fNdata; ++i )
3818  {
3819  void **el = (void**)proxy->At( i );
3820  // coverity[dereference] since this is a member streaming action by definition the collection contains objects and elClass is not null.
3821  *el = elClass->New();
3822  }
3823  }
3824 
3825  proxy->Commit(alternate);
3826 }
3827 
3828 ////////////////////////////////////////////////////////////////////////////////
3829 /// Read leaves into i/o buffers for this branch.
3830 /// Case of a data member within a collection (fType == 41).
3831 
3833 {
3834  ValidateAddress();
3835  if (fObject == 0)
3836  {
3837  // We have nowhere to copy the data (probably because the data member was
3838  // 'dropped' from the current schema) so let's no copy it in a random place.
3839  return;
3840  }
3841 
3842  // STL container sub-branch (contains the elements).
3844  if (!fNdata) {
3845  return;
3846  }
3847 
3848  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3849 
3850  TStreamerInfo *info = GetInfoImp();
3851  if (info == 0) return;
3852 
3855 
3856  // R__ASSERT(0);
3858  b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
3859 
3860  // char **arr = (char **)proxy->At(0);
3861  // char **end = arr + proxy->Size();
3862  // fReadActionSequence->ReadBufferVecPtr(b,arr,end);
3863 
3864  // info->ReadBufferSTLPtrs(b, proxy, fNdata, fID, fOffset);
3865  // for(UInt_t ii=0; ii < fIDs.size(); ++ii) {
3866  // info->ReadBufferSTLPtrs(b, proxy, fNdata, fIDs[ii], fOffset);
3867  // }
3868 }
3869 
3870 ////////////////////////////////////////////////////////////////////////////////
3871 /// Read leaves into i/o buffers for this branch.
3872 /// Case of a data member within a collection (fType == 41).
3873 
3875 {
3876  ValidateAddress();
3877  if (fObject == 0)
3878  {
3879  // We have nowhere to copy the data (probably because the data member was
3880  // 'dropped' from the current schema) so let's no copy it in a random place.
3881  return;
3882  }
3883 
3884  // STL container sub-branch (contains the elements).
3886  if (!fNdata) {
3887  return;
3888  }
3889  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3890 
3891  TStreamerInfo *info = GetInfoImp();
3892  if (info == 0) return;
3893 
3896 
3899 }
3900 
3901 ////////////////////////////////////////////////////////////////////////////////
3902 /// Read leaves into i/o buffers for this branch.
3903 /// Case of a data member within a collection (fType == 41).
3904 
3906 {
3907  ValidateAddress();
3908  if (fObject == 0)
3909  {
3910  // We have nowhere to copy the data (probably because the data member was
3911  // 'dropped' from the current schema) so let's no copy it in a random place.
3912  return;
3913  }
3914 
3915  // STL container sub-branch (contains the elements).
3917  if (!fNdata) {
3918  return;
3919  }
3920  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3921 
3922  TStreamerInfo *info = GetInfoImp();
3923  if (info == 0) return;
3924  // Since info is not null, fReadActionSequence is not null either.
3925 
3926  // Still calling PushPop for the legacy entries.
3929 
3931  b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
3932 }
3933 
3934 ////////////////////////////////////////////////////////////////////////////////
3935 /// Read leaves into i/o buffers for this branch.
3936 /// Case of a TClonesArray (fType == 3).
3937 
3939 {
3940  ValidateAddress();
3941  if (fObject == 0)
3942  {
3943  // We have nowhere to copy the data (probably because the data member was
3944  // 'dropped' from the current schema) so let's no copy it in a random place.
3945  return;
3946  }
3947 
3948  // TClonesArray master branch (has only the number of elements).
3949  Int_t n;
3950  b >> n;
3951  if ((n < 0) || (n > fMaximum)) {
3952  if (IsMissingCollection()) {
3953  n = 0;
3954  b.SetBufferOffset(b.Length()-sizeof(n));
3955  } else {
3956  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());
3957  n = 0;
3958  }
3959  }
3960  fNdata = n;
3961  TClonesArray* clones = (TClonesArray*) fObject;
3962  if (clones->IsZombie()) {
3963  return;
3964  }
3965  // The salient part of Clear is now 'duplicated in ExpandCreateFast (i.e. the
3966  // setting to zero of the unused slots), so we no longer need to call Clear explicitly
3967  // clones->Clear();
3968  clones->ExpandCreateFast(fNdata);
3969 }
3970 
3971 ////////////////////////////////////////////////////////////////////////////////
3972 /// Read leaves into i/o buffers for this branch.
3973 /// Case of a data member within a TClonesArray (fType == 31).
3974 
3976 {
3977  // No need to validate the address here, if we are a member of a split ClonesArray,
3978  // fID is positive
3979  // ValidateAddress();
3980 
3981  if (fObject == 0)
3982  {
3983  // We have nowhere to copy the data (probably because the data member was
3984  // 'dropped' from the current schema) so let's no copy it in a random place.
3985  return;
3986  }
3987 
3988  // TClonesArray sub-branch (contains the elements).
3990  TClonesArray* clones = (TClonesArray*) fObject;
3991  if (clones->IsZombie()) {
3992  return;
3993  }
3994  TStreamerInfo *info = GetInfoImp();
3995  if (info==0) return;
3996  // Since info is not null, fReadActionSequence is not null either.
3997 
3998  // Note, we could (possibly) save some more, by configuring the action
3999  // based on the value of fOnfileObject rather than pushing in on a stack.
4000  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
4001 
4002  char **arr = (char **)clones->GetObjectRef();
4003  char **end = arr + fNdata;
4005 }
4006 
4007 ////////////////////////////////////////////////////////////////////////////////
4008 /// Read leaves into i/o buffers for this branch.
4009 /// For split-class branch, base class branch, data member branch, or top-level branch.
4010 /// which do not have a branch count and are not a counter.
4011 
4013 {
4014  R__ASSERT(fBranchCount==0);
4016 
4017  ValidateAddress();
4018  if (fObject == 0)
4019  {
4020  // We have nowhere to copy the data (probably because the data member was
4021  // 'dropped' from the current schema) so let's no copy it in a random place.
4022  return;
4023  }
4024 
4025  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4026  // If not a TClonesArray or STL container master branch
4027  // or sub-branch and branch inherits from tobject,
4028  // then register with the buffer so that pointers are
4029  // handled properly.
4030  if (TestBit(kBranchObject)) {
4031  b.MapObject((TObject*) fObject);
4032  } else if (TestBit(kBranchAny)) {
4034  }
4035 
4036  fNdata = 1;
4037  TStreamerInfo *info = GetInfoImp();
4038  if (!info) {
4039  return;
4040  }
4041  // Since info is not null, fReadActionSequence is not null either.
4043 }
4044 
4045 ////////////////////////////////////////////////////////////////////////////////
4046 /// Read leaves into i/o buffers for this branch.
4047 /// For split-class branch, base class branch, data member branch, or top-level branch.
4048 /// which do have a branch count and are not a counter.
4049 
4051 {
4053 
4054  ValidateAddress();
4055  if (fObject == 0)
4056  {
4057  // We have nowhere to copy the data (probably because the data member was
4058  // 'dropped' from the current schema) so let's no copy it in a random place.
4059  return;
4060  }
4061 
4062  // If not a TClonesArray or STL container master branch
4063  // or sub-branch and branch inherits from tobject,
4064  // then register with the buffer so that pointers are
4065  // handled properly.
4066  if (TestBit(kBranchObject)) {
4067  b.MapObject((TObject*) fObject);
4068  } else if (TestBit(kBranchAny)) {
4070  }
4071 
4072  fNdata = (Int_t) fBranchCount->GetValue(0, 0);
4073  TStreamerInfo *info = GetInfoImp();
4074  if (!info) {
4075  return;
4076  }
4077  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1); // Here we have a single object that contains a variable size C-style array.
4078  // Since info is not null, fReadActionSequence is not null either.
4080 }
4081 
4082 ////////////////////////////////////////////////////////////////////////////////
4083 /// Read leaves into i/o buffers for this branch.
4084 /// For split-class branch, base class branch, data member branch, or top-level branch.
4085 /// which do not have a branch count and are a counter.
4086 
4088 {
4089  ValidateAddress();
4090  if (fObject == 0)
4091  {
4092  // We have nowhere to copy the data (probably because the data member was
4093  // 'dropped' from the current schema) so let's no copy it in a random place.
4094  return;
4095  }
4096 
4097  // If not a TClonesArray or STL container master branch
4098  // or sub-branch and branch inherits from tobject,
4099  // then register with the buffer so that pointers are
4100  // handled properly.
4101  if (TestBit(kBranchObject)) {
4102  b.MapObject((TObject*) fObject);
4103  } else if (TestBit(kBranchAny)) {
4105  }
4106 
4107  TStreamerInfo *info = GetInfoImp();
4108  if (!info) {
4109  return;
4110  }
4111 
4112  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4113 
4114  // Since info is not null, fReadActionSequence is not null either.
4116  fNdata = (Int_t) GetValue(0, 0);
4117 }
4118 
4119 ////////////////////////////////////////////////////////////////////////////////
4120 /// Read leaves into i/o buffers for this branch.
4121 /// Non TObject, Non collection classes with a custom streamer.
4122 
4124 {
4125  ValidateAddress();
4126  if (fObject == 0)
4127  {
4128  // We have nowhere to copy the data (probably because the data member was
4129  // 'dropped' from the current schema) so let's no copy it in a random place.
4130  return;
4131  }
4132 
4133  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4135 }
4136 
4137 ////////////////////////////////////////////////////////////////////////////////
4138 /// Unconfiguration Fill Leave function.
4139 
4141 {
4142  Fatal("FillLeaves","The FillLeaves function has not been configured for %s",GetName());
4143 }
4144 
4145 ////////////////////////////////////////////////////////////////////////////////
4146 /// Delete any object we may have allocated on a previous call to SetAddress.
4147 
4149 {
4150  if (fObject && TestBit(kDeleteObject)) {
4151  if (IsAutoDelete() && fAddress != (char*)&fObject) {
4152  *((char**) fAddress) = 0;
4153  }
4155  if (fType == 3) {
4156  // -- We are a TClonesArray master branch.
4157  TClonesArray::Class()->Destructor(fObject);
4158  fObject = 0;
4161  // -- We are a pointer to a TClonesArray.
4162  // We must zero the pointer in the object.
4163  *((char**) fAddress) = 0;
4164  }
4165  } else if (fType == 4) {
4166  // -- We are an STL container master branch.
4168 
4169  if (!proxy) {
4170  Warning("ReleaseObject", "Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
4171  fObject = 0;
4172  } else {
4174  if (needDelete && fID >= 0) {
4177  needDelete = !se->TestBit(TStreamerElement::kDoNotDelete);
4178  }
4179  if (needDelete) {
4181  proxy->Clear("force");
4182  }
4183  proxy->Destructor(fObject);
4184  fObject = 0;
4185  }
4187  // -- We are a pointer to an STL container.
4188  // We must zero the pointer in the object.
4189  *((char**) fAddress) = 0;
4190  }
4191  } else {
4192  // We are *not* a TClonesArray master branch and we are *not* an STL container master branch.
4193  TClass* cl = fBranchClass.GetClass();
4194  if (!cl) {
4195  Warning("ReleaseObject", "Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
4196  fObject = 0;
4197  } else {
4199 
4200  if (proxy) {
4201  if (fID >= 0) {
4203  TStreamerElement* se = si->GetElement(fID);
4206  proxy->Clear("force");
4207  }
4210  proxy->Clear("force");
4211  }
4212 
4213  }
4214  cl->Destructor(fObject);
4215  fObject = 0;
4216  }
4217  }
4218  }
4219 }
4220 
4221 ////////////////////////////////////////////////////////////////////////////////
4222 /// Reset a Branch.
4223 ///
4224 /// Existing i/o buffers are deleted.
4225 /// Entries, max and min are reset.
4226 ///
4227 
4229 {
4230  Int_t nbranches = fBranches.GetEntriesFast();
4231  for (Int_t i = 0; i < nbranches; ++i) {
4232  TBranch* branch = (TBranch*) fBranches[i];
4233  branch->Reset(option);
4234  }
4235  fBranchID = -1;
4236  TBranch::Reset(option);
4237 }
4238 
4239 ////////////////////////////////////////////////////////////////////////////////
4240 /// Reset a Branch after a Merge operation (drop data but keep customizations)
4241 ///
4242 
4244 {
4245  Int_t nbranches = fBranches.GetEntriesFast();
4246  for (Int_t i = 0; i < nbranches; ++i) {
4247  TBranch* branch = (TBranch*) fBranches[i];
4248  branch->ResetAfterMerge(info);
4249  }
4251 }
4252 
4253 ////////////////////////////////////////////////////////////////////////////////
4254 /// Set branch address to zero and free all allocated memory.
4255 
4257 {
4258  for (Int_t i = 0; i < fNleaves; ++i) {
4259  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4260  //if (leaf) leaf->SetAddress(0);
4261  leaf->SetAddress(0);
4262  }
4263 
4264  // Note: We *must* do the sub-branches first, otherwise
4265  // we may delete the object containing the sub-branches
4266  // before giving them a chance to cleanup.
4267  Int_t nbranches = fBranches.GetEntriesFast();
4268  for (Int_t i = 0; i < nbranches; ++i) {
4269  TBranch* br = (TBranch*) fBranches[i];
4270  if (br) br->ResetAddress();
4271  }
4272 
4273  //
4274  // SetAddress may have allocated an object.
4275  //
4276 
4277  ReleaseObject();
4278 
4280  fAddress = 0;
4281  fObject = 0;
4282 }
4283 
4284 ////////////////////////////////////////////////////////////////////////////////
4285 /// Release ownership of any allocated objects.
4286 ///
4287 /// Note: This interface was added so that clone trees could
4288 /// be told they do not own the allocated objects.
4289 
4291 {
4294  for (Int_t i = 0; i < nb; ++i) {
4295  TBranch* br = (TBranch*) fBranches[i];
4296  if (br->InheritsFrom(TBranchElement::Class())) {
4297  ((TBranchElement*) br)->ResetDeleteObject();
4298  }
4299  }
4300 }
4301 
4302 ////////////////////////////////////////////////////////////////////////////////
4303 /// Point this branch at an object.
4304 ///
4305 /// For a sub-branch, addr is a pointer to the branch object.
4306 ///
4307 /// For a top-level branch the meaning of addr is as follows:
4308 ///
4309 /// If addr is zero, then we allocate a branch object
4310 /// internally and the branch is the owner of the allocated
4311 /// object, not the caller. However the caller may obtain
4312 /// a pointer to the branch object with GetObject().
4313 ///
4314 /// Example:
4315 /// ~~~ {.cpp}
4316 /// branch->SetAddress(0);
4317 /// Event* event = branch->GetObject();
4318 /// ... Do some work.
4319 /// ~~~
4320 /// If addr is not zero, but the pointer addr points at is
4321 /// zero, then we allocate a branch object and set the passed
4322 /// pointer to point at the allocated object. The caller
4323 /// owns the allocated object and is responsible for deleting
4324 /// it when it is no longer needed.
4325 ///
4326 /// Example:
4327 /// ~~~ {.cpp}
4328 /// Event* event = 0;
4329 /// branch->SetAddress(&event);
4330 /// ... Do some work.
4331 /// delete event;
4332 /// event = 0;
4333 /// ~~~
4334 /// If addr is not zero and the pointer addr points at is
4335 /// also not zero, then the caller has allocated a branch
4336 /// object and is asking us to use it. The caller owns it
4337 /// and must delete it when it is no longer needed.
4338 ///
4339 /// Example:
4340 /// ~~~ {.cpp}
4341 /// Event* event = new Event();
4342 /// branch->SetAddress(&event);
4343 /// ... Do some work.
4344 /// delete event;
4345 /// event = 0;
4346 /// ~~~
4347 /// These rules affect users of TTree::Branch(),
4348 /// TTree::SetBranchAddress(), and TChain::SetBranchAddress()
4349 /// as well because those routines call this one.
4350 ///
4351 /// An example of a tree with branches with objects allocated
4352 /// and owned by us:
4353 /// ~~~ {.cpp}
4354 /// TFile* f1 = new TFile("myfile_original.root");
4355 /// TTree* t1 = (TTree*) f->Get("MyTree");
4356 /// TFile* f2 = new TFile("myfile_copy.root", "recreate");
4357 /// TTree* t2 = t1->Clone(0);
4358 /// for (Int_t i = 0; i < 10; ++i) {
4359 /// t1->GetEntry(i);
4360 /// t2->Fill();
4361 /// }
4362 /// t2->Write()
4363 /// delete f2;
4364 /// f2 = 0;
4365 /// delete f1;
4366 /// f1 = 0;
4367 /// ~~~
4368 /// An example of a branch with an object allocated by us,
4369 /// but owned by the caller:
4370 /// ~~~ {.cpp}
4371 /// TFile* f = new TFile("myfile.root", "recreate");
4372 /// TTree* t = new TTree("t", "A test tree.")
4373 /// Event* event = 0;
4374 /// TBranchElement* br = t->Branch("event.", &event);
4375 /// for (Int_t i = 0; i < 10; ++i) {
4376 /// ... Fill event with meaningful data in some way.
4377 /// t->Fill();
4378 /// }
4379 /// t->Write();
4380 /// delete event;
4381 /// event = 0;
4382 /// delete f;
4383 /// f = 0;
4384 /// ~~~
4385 /// Notice that the only difference between this example
4386 /// and the following example is that the event pointer
4387 /// is zero when the branch is created.
4388 ///
4389 /// An example of a branch with an object allocated and
4390 /// owned by the caller:
4391 /// ~~~ {.cpp}
4392 /// TFile* f = new TFile("myfile.root", "recreate");
4393 /// TTree* t = new TTree("t", "A test tree.")
4394 /// Event* event = new Event();
4395 /// TBranchElement* br = t->Branch("event.", &event);
4396 /// for (Int_t i = 0; i < 10; ++i) {
4397 /// ... Fill event with meaningful data in some way.
4398 /// t->Fill();
4399 /// }
4400 /// t->Write();
4401 /// delete event;
4402 /// event = 0;
4403 /// delete f;
4404 /// f = 0;
4405 /// ~~~
4406 /// If AutoDelete is on (see TBranch::SetAutoDelete),
4407 /// the top level objet will be deleted and recreate
4408 /// each time an entry is read, whether or not the
4409 /// TTree owns the object.
4410 
4412 {
4413  //
4414  // Don't bother if we are disabled.
4415  //
4416 
4417  if (TestBit(kDoNotProcess)) {
4418  return;
4419  }
4420 
4421  //
4422  // FIXME: When would this happen?
4423  //
4424 
4425  if (fType < -1) {
4426  return;
4427  }
4428 
4429  //
4430  // Special case when called from code generated by TTree::MakeClass.
4431  //
4432 
4433  if (Long_t(addr) == -1) {
4434  // FIXME: Do we have to release an object here?
4435  // ReleaseObject();
4436  fAddress = (char*) -1;
4437  fObject = (char*) -1;
4439  return;
4440  }
4441 
4442  //
4443  // Reset last read entry number, we have a new user object now.
4444  //
4445 
4446  fReadEntry = -1;
4447 
4448  //
4449  // Make sure our branch class is instantiated.
4450  //
4451  TClass* clOfBranch = fBranchClass.GetClass();
4452  if( fTargetClass.GetClassName()[0] ) {
4453  clOfBranch = fTargetClass;
4454  }
4455 
4456  //
4457  // Try to build the streamer info.
4458  //
4459 
4460  TStreamerInfo *info = GetInfoImp();
4461 
4462  // FIXME: Warn about failure to get the streamer info here?
4463 
4464  //
4465  // We may have allocated an object last time we were called.
4466  //
4467 
4468  if (fObject && TestBit(kDeleteObject)){
4469  ReleaseObject();
4470  }
4471 
4472  //
4473  // Remember the pointer to the pointer to our object.
4474  //
4475 
4476  fAddress = (char*) addr;
4477  if (fAddress != (char*)(&fObject)) {
4478  fObject = 0;
4479  }
4481 
4482  //
4483  // Do special stuff if we got called from a MakeClass class.
4484  // Allow sub-branches to have independently set addresses.
4485  //
4486 
4487  if (fTree->GetMakeClass()) {
4488  if (fID > -1) {
4489  // We are *not* a top-level branch.
4490  if (!info) {
4491  // No streamer info, give up.
4492  // FIXME: We should have an error message here.
4493  fObject = fAddress;
4494  } else {
4495  // Compensate for the fact that the i/o routines
4496  // will add the streamer offset to the address.
4497  fObject = fAddress - info->TStreamerInfo::GetElementOffset(fID);
4498  }
4499  return;
4500  }
4501  }
4502 
4503  //
4504  // Check whether the container type is still the same
4505  // to support schema evolution; what is written on the file
4506  // may no longer match the class code which is loaded.
4507  //
4508 
4509  if (fType == 3) {
4510  // split TClonesArray, counter/master branch.
4511  TClass* clm = fClonesClass;
4512  if (clm) {
4513  // In case clm derives from an abstract class.
4514  clm->BuildRealData();
4515  clm->GetStreamerInfo();
4516  }
4517  TClass* newType = GetCurrentClass();
4518  if (newType && (newType != TClonesArray::Class())) {
4519  // The data type of the container has changed.
4520  //
4521  // Let's check if it is a compatible type:
4522  Bool_t matched = kFALSE;
4523  if (newType->GetCollectionProxy()) {
4524  TClass *content = newType->GetCollectionProxy()->GetValueClass();
4525  if (clm == content) {
4526  matched = kTRUE;
4527  } else {
4528  Warning("SetAddress", "The type of %s was changed from TClonesArray to %s but the content do not match (was %s)!", GetName(), newType->GetName(), GetClonesName());
4529  }
4530  } else {
4531  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());
4532  }
4533  if (matched) {
4534  // Change from 3/31 to 4/41
4535  SetType(4);
4536  // Set the proxy.
4537  fSTLtype = newType->GetCollectionType();
4538  fCollProxy = newType->GetCollectionProxy()->Generate();
4539 
4541  SetReadLeavesPtr();
4542  SetFillLeavesPtr();
4543 
4549  } else {
4551  }
4552  } else {
4553  // FIXME: Must maintain fObject here as well.
4554  fAddress = 0;
4555  }
4556  }
4557  } else if (fType == 4) {
4558  // split STL container, counter/master branch.
4559  TClass* newType = GetCurrentClass();
4560  if (newType && (newType != GetCollectionProxy()->GetCollectionClass())) {
4561  // Let's check if it is a compatible type:
4562  TVirtualCollectionProxy* newProxy = newType->GetCollectionProxy();
4564  if (newProxy && (oldProxy->GetValueClass() == newProxy->GetValueClass()) && ((!oldProxy->GetValueClass() && (oldProxy->GetType() == newProxy->GetType())) || (oldProxy->GetValueClass() && (oldProxy->HasPointers() == newProxy->HasPointers())))) {
4565  delete fCollProxy;
4566  Int_t nbranches = GetListOfBranches()->GetEntries();
4567  fCollProxy = newType->GetCollectionProxy()->Generate();
4569  for (Int_t i = 0; i < nbranches; ++i) {
4571  br->fCollProxy = 0;
4572  if (br->fReadActionSequence) {
4573  br->SetReadActionSequence();
4574  }
4575  if (br->fFillActionSequence) {
4576  br->SetFillActionSequence();
4577  }
4578  }
4581  SetReadLeavesPtr();
4582  SetFillLeavesPtr();
4583  delete fIterators;
4584  delete fPtrIterators;
4590  } else {
4592  }
4593  }
4594  else if (newProxy && (oldProxy->HasPointers() == newProxy->HasPointers()) && (oldProxy->GetValueClass()!=0) && (newProxy->GetValueClass()!=0)) {
4595  // Let see if there is a rule to convert the content of the collection into each other.
4596  if (newType->GetSchemaRules()->HasRuleWithSourceClass( oldProxy->GetCollectionClass()->GetName())) {
4597  TClass *oldValueClass = oldProxy->GetValueClass();
4598  delete fCollProxy;
4599  Int_t nbranches = GetListOfBranches()->GetEntries();
4600  fCollProxy = newType->GetCollectionProxy()->Generate();
4602  for (Int_t i = 0; i < nbranches; ++i) {
4604  br->fCollProxy = 0;
4605  if (br->fBranchClass == oldValueClass) {
4607  }
4608  if (br->fReadActionSequence) {
4609  br->SetReadActionSequence();
4610  }
4611  if (br->fFillActionSequence) {
4612  br->SetFillActionSequence();
4613  }
4614  }
4617  SetReadLeavesPtr();
4618  SetFillLeavesPtr();
4619  delete fIterators;
4620  delete fPtrIterators;
4626  } else {
4628  }
4629  } else {
4630  Error("SetAddress","For %s, we can not convert %s into %s\n",
4631  GetName(),oldProxy->GetCollectionClass()->GetName(),newType->GetName());
4632  fAddress = 0;
4633  fObject = 0;
4634  return;
4635  }
4636  }
4637  else if ((newType == TClonesArray::Class()) && (oldProxy->GetValueClass() && !oldProxy->HasPointers() && oldProxy->GetValueClass()->IsTObject()))
4638  {
4639  // The new collection and the old collection are not compatible,
4640  // we cannot use the new collection to read the data.
4641  // Actually we could check if the new collection is a
4642  // compatible ROOT collection.
4643 
4644  // We cannot insure that the TClonesArray is set for the
4645  // proper class (oldProxy->GetValueClass()), so we assume that
4646  // the transformation was done properly by the class designer.
4647 
4648  // Change from 4/41 to 3/31
4649  SetType(3);
4650  // Reset the proxy.
4651  fSTLtype = kNone;
4652  switch(fStreamerType) {
4656  break;
4660  break;
4663  break;
4664  }
4665  fClonesClass = oldProxy->GetValueClass();
4667  delete fCollProxy;
4668  fCollProxy = 0;
4669  TClass* clm = fClonesClass;
4670  if (clm) {
4671  clm->BuildRealData(); //just in case clm derives from an abstract class
4672  clm->GetStreamerInfo();
4673  }
4675  SetReadLeavesPtr();
4676  SetFillLeavesPtr();
4677  delete fIterators;
4678  fIterators = 0;
4679  delete fPtrIterators;
4680  fPtrIterators =0;
4681  } else {
4682  // FIXME: We must maintain fObject here as well.
4683  Error("SetAddress","For %s can not convert %s into %s\n",GetName(),GetCurrentClass()->GetName(),newType->GetName());
4684  fAddress = 0;
4685  return;
4686  }
4687  } else {
4688  if (!fIterators && !fPtrIterators) {
4694  } else {
4696  }
4697  }
4698  }
4699  }
4700 
4701  //
4702  // Establish the semantics of fObject and fAddress.
4703  //
4704  // Top-level branch:
4705  // fObject is a ptr to the object,
4706  // fAddress is a ptr to a pointer to the object.
4707  //
4708  // Sub-branch:
4709  // fObject is a ptr to the object,
4710  // fAddress is the same as fObject.
4711  //
4712  //
4713  // There are special cases for TClonesArray and STL containers.
4714  // If there is no user-provided object, we allocate one. We must
4715  // also initialize any STL container proxy.
4716  //
4717 
4718  if (fType == 3) {
4719  // -- We are a TClonesArray master branch.
4720  if (fAddress) {
4721  // -- We have been given a non-zero address, allocate if necessary.
4723  // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
4724  // Case of an embedded TClonesArray.
4725  fObject = fAddress;
4726  // Check if it has already been properly built.
4727  TClonesArray* clones = (TClonesArray*) fObject;
4728  if (!clones->GetClass()) {
4730  }
4731  } else {
4732  // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
4733  // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
4734  if ((fStreamerType != -1) &&
4737  Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
4738  } else if (fStreamerType == -1) {
4739  // -- We are a top-level branch.
4740  TClonesArray** pp = (TClonesArray**) fAddress;
4741  if (!*pp) {
4742  // -- Caller wants us to allocate the clones array, but they will own it.
4743  *pp = new TClonesArray(fClonesClass);
4744  }
4745  fObject = (char*) *pp;
4746  } else {
4747  // -- We are a pointer to a TClonesArray.
4748  // Note: We do this so that the default constructor,
4749  // or the i/o constructor can be lazy.
4750  TClonesArray** pp = (TClonesArray**) fAddress;
4751  if (!*pp) {
4752  // -- Caller wants us to allocate the clones array, but they will own it.
4753  *pp = new TClonesArray(fClonesClass);
4754  }
4755  fObject = (char*) *pp;
4756  }
4757  }
4758  } else {
4759  // -- We have been given a zero address, allocate for top-level only.
4761  // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
4762  // Case of an embedded TClonesArray.
4763  Error("SetAddress", "Embedded TClonesArray given a zero address for branch '%s'", GetName());
4764  } else {
4765  // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
4766  // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
4767  if ((fStreamerType != -1) &&
4770  Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
4771  } else if (fStreamerType == -1) {
4772  // -- We are a top-level branch.
4773  // Idea: Consider making a zero address not allocate.
4775  fObject = (char*) new TClonesArray(fClonesClass);
4776  fAddress = (char*) &fObject;
4777  } else {
4778  // -- We are a sub-branch which is a pointer to a TClonesArray.
4779  Error("SetAddress", "Embedded pointer to a TClonesArray given a zero address for branch '%s'", GetName());
4780  }
4781  }
4782  }
4783  } else if (fType == 4) {
4784  // -- We are an STL container master branch.
4785  //
4786  // Initialize fCollProxy.
4788  if (fAddress) {
4789  // -- We have been given a non-zero address, allocate if necessary.
4793  // We are *not* a top-level branch and we are *not* a pointer to an STL container.
4794  // Case of an embedded STL container.
4795  // Note: We test for the kObject and kAny types to support
4796  // the (unwise) choice of inheriting from an STL container.
4797  fObject = fAddress;
4798  } else {
4799  // We are either a top-level branch or subbranch which is a pointer to an STL container.
4800  // Streamer type should be -1 (for a top-level branch) or kSTLp here.
4802  Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
4803  } else if (fStreamerType == -1) {
4804  // -- We are a top-level branch.
4805  void** pp = (void**) fAddress;
4806  if (!*pp) {
4807  // -- Caller wants us to allocate the STL container, but they will own it.
4808  *pp = proxy->New();
4809  if (!(*pp)) {
4810  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4811  // FIXME: Should we do this? Lots of other code wants
4812  // fAddress to be zero if no fObject, but is
4813  // that a good thing?
4814  fAddress = 0;
4815  }
4816  }
4817  fObject = (char*) *pp;
4818  } else {
4819  // -- We are a pointer to an STL container.
4820  // Note: We do this so that the default constructor,
4821  // or the i/o constructor can be lazy.
4822  void** pp = (void**) fAddress;
4823  if (!*pp) {
4824  // -- Caller wants us to allocate the STL container, but they will own it.
4825  *pp = proxy->New();
4826  if (!(*pp)) {
4827  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4828  // FIXME: Should we do this? Lots of other code wants
4829  // fAddress to be zero if no fObject, but is
4830  // that a good thing?
4831  fAddress = 0;
4832  }
4833  }
4834  fObject = (char*) *pp;
4835  }
4836  }
4837  } else {
4838  // -- We have been given a zero address, allocate for top-level only.
4842  // We are *not* a top-level branch and we are *not* a pointer to an STL container.
4843  // Case of an embedded STL container.
4844  // Note: We test for the kObject and kAny types to support
4845  // the (unwise) choice of inheriting from an STL container.
4846  Error("SetAddress", "Embedded STL container given a zero address for branch '%s'", GetName());
4847  } else {
4848  // We are either a top-level branch or sub-branch which is a pointer to an STL container.
4849  // Streamer type should be -1 (for a top-level branch) or kSTLp here.
4851  Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
4852  } else if (fStreamerType == -1) {
4853  // -- We are a top-level branch, allocate.
4855  fObject = (char*) proxy->New();
4856  if (fObject) {
4857  fAddress = (char*) &fObject;
4858  } else {
4859  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4860  // FIXME: Should we do this? Lots of other code wants
4861  // fAddress to be zero if no fObject, but is
4862  // that a good thing?
4863  fAddress = 0;
4864  }
4865  } else {
4866  // -- We are a sub-branch which is a pointer to an STL container.
4867  Error("SetAddress", "Embedded pointer to an STL container given a zero address for branch '%s'", GetName());
4868  }
4869  }
4870  }
4871  } else if (fType == 41) {
4872  // -- We are an STL container sub-branch.
4873  // Initialize fCollProxy.
4875  // We are not at top-level branch.
4876  fObject = fAddress;
4877  } else if (fID < 0) {
4878  // -- We are a top-level branch.
4879  char** pp = (char**) fAddress;
4880  if (pp && *pp) {
4881  // -- Caller provided an i/o buffer for us to use.
4882  fObject = *pp;
4883  } else {
4884  // -- Caller did not provide an i/o buffer for us to use, we must make one for ourselves.
4885  if (clOfBranch) {
4886  if (!pp) {
4887  // -- Caller wants us to own the object.
4889  }
4890  fObject = (char*) clOfBranch->New();
4891  if (pp) {
4892  *pp = fObject;
4893  } else {
4894  fAddress = (char*) &fObject;
4895  }
4896  } else {
4897  Error("SetAddress", "I have no TClass for branch %s, so I cannot allocate an I/O buffer!", GetName());
4898  if (pp) {
4899  fObject = 0;
4900  *pp = 0;
4901  }
4902  }
4903  }
4904  } else {
4905  // -- We are *not* a top-level branch.
4906  fObject = fAddress;
4907  }
4908 
4909  if (!info) {
4910  // FIXME: We need and error message here, no streamer info, so cannot set offsets.
4911  return;
4912  }
4913 
4914  // We do this only once because it depends only on
4915  // the type of our object, not on its address.
4916  if (!fInitOffsets) {
4918  }
4919 
4920  // We are split, recurse down to our sub-branches.
4921  //
4922  // FIXME: This is a tail recursion, we burn stack.
4923  Int_t nbranches = fBranches.GetEntriesFast();
4924  for (Int_t i = 0; i < nbranches; ++i) {
4925  TBranch* abranch = (TBranch*) fBranches.UncheckedAt(i);
4926  // FIXME: This is a tail recursion!
4928  abranch->SetAddress(fObject + fBranchOffset[i]);
4929  abranch->SetBit(kAddressSet);
4930  } else {
4931  // When the member is missing, just leave the address alone
4932  // (since setting explicitly to 0 would trigger error/warning
4933  // messages).
4934  // abranch->SetAddress(0);
4935  abranch->SetBit(kAddressSet);
4936  }
4937  }
4938 }
4939 
4940 ////////////////////////////////////////////////////////////////////////////////
4941 /// Reset the basket size for all sub-branches of this branch element.
4942 
4944 {
4945  TBranch::SetBasketSize(buffsize);
4946  Int_t nbranches = fBranches.GetEntriesFast();
4947  for (Int_t i = 0; i < nbranches; ++i) {
4948  TBranch* branch = (TBranch*) fBranches[i];
4949  branch->SetBasketSize(fBasketSize);
4950  }
4951 }
4952 
4953 ////////////////////////////////////////////////////////////////////////////////
4954 /// Set the branch counter for this branch.
4955 
4957 {
4958  fBranchCount = brOfCounter;
4959  if (fBranchCount==0) return;
4960 
4961  TLeafElement* leafOfCounter = (TLeafElement*) brOfCounter->GetListOfLeaves()->At(0);
4962  TLeafElement* leaf = (TLeafElement*) GetListOfLeaves()->At(0);
4963  if (leafOfCounter && leaf) {
4964  leaf->SetLeafCount(leafOfCounter);
4965  } else {
4966  if (!leafOfCounter) {
4967  Warning("SetBranchCount", "Counter branch %s for branch %s has no leaves!", brOfCounter->GetName(), GetName());
4968  }
4969  if (!leaf) {
4970  Warning("SetBranchCount", "Branch %s has no leaves!", GetName());
4971  }
4972  }
4973 }
4974 
4975 ////////////////////////////////////////////////////////////////////////////////
4976 /// Set the branch in a mode where the object are decomposed
4977 /// (Also known as MakeClass mode).
4978 /// Return whether the setting was possible (it is not possible for
4979 /// TBranch and TBranchObject).
4980 
4982 {
4983  if (decomposeObj)
4984  SetBit(kDecomposedObj); // Same as SetBit(kMakeClass)
4985  else
4987 
4988  Int_t nbranches = fBranches.GetEntriesFast();
4989  for (Int_t i = 0; i < nbranches; ++i) {
4990  TBranchElement* branch = (TBranchElement*) fBranches[i];
4991  branch->SetMakeClass(decomposeObj);
4992  }
4993  SetReadLeavesPtr();
4994  SetFillLeavesPtr();
4995 
4996  return kTRUE;
4997 }
4998 
4999 ////////////////////////////////////////////////////////////////////////////////
5000 /// Set object this branch is pointing to.
5001 
5003 {
5004  if (TestBit(kDoNotProcess)) {
5005  return;
5006  }
5007  fObject = (char*)obj;
5008  SetAddress( &fObject );
5009 }
5010 
5011 ////////////////////////////////////////////////////////////////////////////////
5012 /// Set offset of the object (to which the data member represented by this
5013 /// branch belongs) inside its containing object (if any).
5014 
5016 {
5017  // We need to make sure that the Read and Write action's configuration
5018  // properly reflect this value.
5019 
5020  if (fReadActionSequence) {
5022  }
5023  if (fFillActionSequence) {
5025  }
5026  fOffset = offset;
5027 }
5028 
5029 ////////////////////////////////////////////////////////////////////////////////
5030 /// Set the sequence of actions needed to read the data out of the buffer.
5031 
5033 {
5034  if (fInfo == 0) {
5035  // We are called too soon. We will be called again by InitInfo
5036  return;
5037  }
5038 
5039  // Get the action sequence we need to copy for reading.
5042  if (fType == 41) {
5044  original = fInfo->GetReadMemberWiseActions(kTRUE);
5045  } else {
5046  TVirtualStreamerInfo *info = GetInfoImp();
5047  if (GetParentClass() == info->GetClass()) {
5050  } else {
5052  }
5053  } else if (GetCollectionProxy()) {
5054  // Base class and embedded objects.
5055 
5057  original = transient;
5058  }
5059  }
5060  } else if (fType == 31) {
5061  original = fInfo->GetReadMemberWiseActions(kTRUE);
5062  } else if (0<=fType && fType<=2) {
5063  // Note: this still requires the ObjectWise sequence to not be optimized!
5064  original = fInfo->GetReadMemberWiseActions(kFALSE);
5065  }
5066  if (original) {
5067  fIDs.insert(fIDs.begin(),fID); // Include the main element in the sequence.
5070  fIDs.erase(fIDs.begin());
5071  }
5072  delete transient;
5073 }
5074 
5075 ////////////////////////////////////////////////////////////////////////////////
5076 /// Set the ReadLeaves pointer to execute the expected operations.
5077 
5079 {
5080  if (TestBit(kDecomposedObj)) {
5082  } else if (fType == 4) {
5084  } else if (fType == 41) {
5088  } else {
5090  }
5091  } else {
5093  }
5094  } else if (fType == 3) {
5096  } else if (fType == 31) {
5098  } else if (fType < 0) {
5100  } else if (fType == 0 && fID == -1) {
5101  // top-level branch.
5103  if (hasCustomStreamer) {
5104  // We are in the case where the object did *not* have a custom
5105  // Streamer when the TTree was written but now *does* have a custom
5106  // Streamer thus we must use it.
5108  } else {
5110  }
5111  } else if (fType <= 2) {
5112  // split-class branch, base class branch or data member branch.
5113  if (fBranchCount) {
5117  } else {
5119  }
5120  } else {
5121  Fatal("SetReadLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5122  }
5123 
5125 }
5126 
5127 ////////////////////////////////////////////////////////////////////////////////
5128 /// Set the sequence of actions needed to write the data out from the buffer.
5129 
5131 {
5132  if (fInfo == 0) {
5133  // We are called too soon. We will be called again by InitInfo
5134  return;
5135  }
5136 
5137  // Get the action sequence we need to copy for reading.
5140  if (fType == 41) {
5142  original = fInfo->GetWriteMemberWiseActions(kTRUE);
5143  } else {
5144  TVirtualStreamerInfo *info = GetInfoImp();
5145  if (GetParentClass() == info->GetClass()) {
5146  //if( fTargetClass.GetClassName()[0] && fBranchClass != fTargetClass ) {
5147  // original = GetCollectionProxy()->GetConversionWriteMemberWiseActions(fBranchClass.GetClass());
5148  //} else {
5150  //}
5151  } else if (GetCollectionProxy()) {
5152  // Base class and embedded objects.
5153 
5155  original = transient;
5156  }
5157  }
5158  } else if (fType == 31) {
5159  original = fInfo->GetWriteMemberWiseActions(kTRUE);
5160  } else if (0<=fType && fType<=2) {
5161  // Note: this still requires the ObjectWise sequence to not be optimized!
5162  original = fInfo->GetWriteMemberWiseActions(kFALSE);
5163  }
5164  if (original) {
5165  fIDs.insert(fIDs.begin(),fID); // Include the main element in the sequence.
5168  fIDs.erase(fIDs.begin());
5169  }
5170  delete transient;
5171 
5172 }
5173 
5174 ////////////////////////////////////////////////////////////////////////////////
5175 /// Set the FillLeaves pointer to execute the expected operations.
5176 
5178 {
5179  if (fTree->GetMakeClass() && ((fType==3)||(fType==31))) {
5181  } else if (fType == 4) {
5183  } else if (fType == 41) {
5187  } else {
5189  }
5192  } else {
5194  }
5195  } else if (fType == 3) {
5197  } else if (fType == 31) {
5199  } else if (fType < 0) {
5201  } else if (fType <=2) {
5202  //split-class branch, base class branch, data member branch, or top-level branch.
5203  if (fBranchCount) {
5207  } else {
5209  }
5210  } else {
5211  Fatal("SetFillLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5212  }
5213 
5215 }
5216 
5217 ////////////////////////////////////////////////////////////////////////////////
5218 /// Set the name of the class of the in-memory object into which the data will
5219 /// loaded.
5220 
5222 {
5223  if (name == 0) return;
5224 
5225  if (strcmp(fTargetClass.GetClassName(),name) != 0 )
5226  {
5227  // We are changing target class, let's reset the meta information and
5228  // the sub-branches.
5229 
5230  fInfo = 0;
5231  fInit = kFALSE;
5232  fInitOffsets = kFALSE;
5233  delete fReadActionSequence;
5234  fReadActionSequence = 0;
5235  delete fFillActionSequence;
5236  fFillActionSequence = 0;
5237 
5238  Int_t nbranches = fBranches.GetEntriesFast();
5239  for (Int_t i = 0; i < nbranches; ++i) {
5241  if (sub->fTargetClass == fTargetClass ) {
5242  sub->SetTargetClass(name);
5243  }
5244  if (sub->fParentClass == fTargetClass ) {
5245  sub->SetParentClass(TClass::GetClass(name));
5246  }
5247  }
5248  fTargetClass = name;
5249  }
5250 
5251 }
5252 
5253 ////////////////////////////////////////////////////////////////////////////////
5254 /// If the branch address is not set, we set all addresses starting with
5255 /// the top level parent branch. This is required to be done in order for
5256 /// GetOffset to be correct and for GetEntry to run.
5257 
5259 {
5260  // Check to see if the user changed the branch address on us.
5261  ValidateAddress();
5262 
5263  if (fAddress || fTree->GetMakeClass()) {
5264  // -- Do nothing if already setup or if we are a MakeClass tree.
5265  return;
5266  }
5268 }
5269 
5270 ////////////////////////////////////////////////////////////////////////////////
5271 /// If the branch address is not set, we set all addresses starting with
5272 /// the top level parent branch. This is required to be done in order for
5273 /// GetOffset to be correct and for GetEntry to run.
5274 
5276 {
5278  // -- Do nothing if we have been told not to.
5279  // Or the data member in this branch is not longer part of the
5280  // parent's layout.
5281  return;
5282  }
5283 
5284  //--------------------------------------------------------------------------
5285  // Check if we are splited STL collection of pointers
5286  /////////////////////////////////////////////////////////////////////////////
5287 
5289  {
5290  TBranchElement *parent = (TBranchElement *)GetMother()->GetSubBranch( this );
5291 
5292  // Make sure the StreamerInfo is loaded and initialized.
5293  GetInfoImp();
5294 
5295  if( !parent->GetAddress() )
5296  parent->SetAddress( 0 );
5297  return;
5298  }
5299 
5300  //--------------------------------------------------------------------------
5301  // Any other case
5302  /////////////////////////////////////////////////////////////////////////////
5303 
5304  TBranchElement* mother = (TBranchElement*) GetMother();
5305  if (!mother) {
5306  return;
5307  }
5308  TClass* cl = TClass::GetClass(mother->GetClassName());
5309 
5310  // Make sure the StreamerInfo is loaded and initialized.
5311  GetInfoImp();
5312 
5313  if (!cl) {
5314  return;
5315  }
5316 
5317  if (!mother->GetAddress()) {
5318  // -- Our top-level branch has no address.
5319  Bool_t motherStatus = mother->TestBit(kDoNotProcess);
5320  mother->ResetBit(kDoNotProcess);
5321  // Note: This will allocate an object.
5322  mother->SetAddress(0);
5323  mother->SetBit(kDoNotProcess, motherStatus);
5324  }
5325 }
5326 
5327 ////////////////////////////////////////////////////////////////////////////////
5328 /// Stream an object of class TBranchElement.
5329 
5330 void TBranchElement::Streamer(TBuffer& R__b)
5331 {
5332  if (R__b.IsReading()) {
5333  R__b.ReadClassBuffer(TBranchElement::Class(), this);
5338  // The fAddress and fObject data members are not persistent,
5339  // therefore we do not own anything.
5340  // Also clear the bit possibly set by the schema evolution.
5342  // Fixup a case where the TLeafElement was missing
5343  if ((fType == 0) && (fLeaves.GetEntriesFast() == 0)) {
5344  TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
5345  leaf->SetTitle(GetTitle());
5346  fNleaves = 1;
5347  fLeaves.Add(leaf);
5348  fTree->GetListOfLeaves()->Add(leaf);
5349  }
5350  // SetReadLeavesPtr();
5351  }
5352  else {
5353  TDirectory* dirsav = fDirectory;
5354  fDirectory = 0; // to avoid recursive calls
5355  {
5356  // Save class version.
5357  Int_t classVersion = fClassVersion;
5358  // Record only positive 'version number'
5359  if (fClassVersion < 0) {
5361  }
5362  // TODO: Should we clear the kDeleteObject bit before writing?
5363  // If we did we would have to remember the old value and
5364  // put it back, we wouldn't want to forget that we owned
5365  // something just because we got written to disk.
5367  // Restore class version.
5368  fClassVersion = classVersion;
5369  }
5370  //
5371  // Mark all streamer infos used by this branch element
5372  // to be written to our output file.
5373  //
5374  {
5375  R__b.ForceWriteInfo(GetInfoImp(), kTRUE);
5376  }
5377  //
5378  // If we are a clones array master branch, or an
5379  // STL container master branch, we must also mark
5380  // the streamer infos used by the value class to
5381  // be written to our output file.
5382  //
5383  if (fType == 3) {
5384  // -- TClonesArray, counter/master branch
5385  //
5386  // We must mark the streamer info for the
5387  // value class to be written to the file.
5388  //
5389  TClass* cl = fClonesClass;
5390  if (cl) {
5391  R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
5392  }
5393  }
5394  else if (fType == 4) {
5395  // -- STL container, counter/master branch
5396  //
5397  // We must mark the streamer info for the
5398  // value class to be written to the file.
5399  //
5401  if (cp) {
5402  TClass* cl = cp->GetValueClass();
5403  if (cl) {
5404  R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
5405  }
5406  }
5407  }
5408  // If we are in a separate file, then save
5409  // ourselves as an independent key.
5410  if (!dirsav) {
5411  // Note: No need to restore fDirectory, it was already zero.
5412  return;
5413  }
5414  if (!dirsav->IsWritable()) {
5415  fDirectory = dirsav;
5416  return;
5417  }
5418  TDirectory* pdirectory = fTree->GetDirectory();
5419  if (!pdirectory) {
5420  fDirectory = dirsav;
5421  return;
5422  }
5423  const char* treeFileName = pdirectory->GetFile()->GetName();
5424  TBranch* mother = GetMother();
5425  const char* motherFileName = treeFileName;
5426  if (mother && (mother != this)) {
5427  motherFileName = mother->GetFileName();
5428  }
5429  if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
5430  dirsav->WriteTObject(this);
5431  }
5432  fDirectory = dirsav;
5433  }
5434 }
5435 
5436 ////////////////////////////////////////////////////////////////////////////////
5437 /// Split class cl into sub-branches of this branch.
5438 ///
5439 /// Create a sub-branch of this branch for each non-empty,
5440 /// non-abstract base class of cl (unless we are a sub-branch
5441 /// of a TClonesArray or an STL container, in which case we
5442 /// do *not* create a sub-branch), and for each non-split data
5443 /// member of cl.
5444 ///
5445 /// Note: We do *not* create sub-branches for base classes of cl
5446 /// if we are a sub-branch of a TClonesArray or an STL container.
5447 ///
5448 /// Note: We do *not* create sub-branches for data members which
5449 /// have a class type and which we are splitting.
5450 ///
5451 /// Note: The above rules imply that the branch heirarchy increases
5452 /// in depth only for base classes of cl (unless we are inside
5453 /// of a TClonesArray or STL container, in which case the depth
5454 /// does *not* increase, the base class is elided) and for
5455 /// TClonesArray or STL container data members (which have one
5456 /// additional level of sub-branches). The only other way the
5457 /// depth increases is when the top-level branch has a split
5458 /// class data member, in that case the constructor will create
5459 /// a sub-branch for it. In other words, the interior nodes of
5460 /// the branch tree are all either: base class nodes; split
5461 /// class nodes which are direct sub-branches of top-level nodes
5462 /// (created by TClass::Bronch usually); or TClonesArray or STL
5463 /// container master nodes.
5464 ///
5465 /// Note: The exception to the above is for the top-level branches,
5466 /// Tree::Bronch creates nodes for everything in that case,
5467 /// except for a TObject base class of a class which has the
5468 /// can ignore tobject streamer flag set.
5469 
5470 Int_t TBranchElement::Unroll(const char* name, TClass* clParent, TClass* cl, char* ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
5471 {
5472  //----------------------------------------------------------------------------
5473  // Handling the case of STL collections of pointers
5474  /////////////////////////////////////////////////////////////////////////////
5475 
5476  Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
5477  splitlevel %= TTree::kSplitCollectionOfPointers;
5478 
5479  TString branchname;
5480 
5481  if ((cl == TObject::Class()) && clParent->CanIgnoreTObjectStreamer()) {
5482  return 0;
5483  }
5484 
5485  TStreamerInfo* sinfo = fTree->BuildStreamerInfo(cl);
5486 
5487  //
5488  // Do nothing if we couldn't build the streamer info for cl.
5489  //
5490 
5491  if (!sinfo) {
5492  return 0;
5493  }
5494 
5495  Int_t ndata = sinfo->GetNelement();
5496 
5497  if ((ndata == 1) && cl->GetCollectionProxy() && !strcmp(sinfo->GetElement(0)->GetName(), "This")) {
5498  // -- Class cl is an STL collection, refuse to split it.
5499  // Question: Why? We certainly could by switching to the value class.
5500  // Partial Answer: Only the branch element constructor can split STL containers.
5501  return 1;
5502  }
5503 
5504  for (Int_t elemID = 0; elemID < ndata; ++elemID) {
5505  // -- Loop over all the streamer elements and create sub-branches as needed.
5506  TStreamerElement* elem = sinfo->GetElement(elemID);
5507  if (elem->IsA() == TStreamerArtificial::Class()) {
5508  continue;
5509  }
5510  if (elem->TestBit(TStreamerElement::kRepeat)) {
5511  continue;
5512  }
5514  continue;
5515  }
5516  Int_t offset = elem->GetOffset();
5517  // FIXME: An STL container as a base class gets TStreamerSTL as its class, so this test is not enough.
5518  // See InitializeOffsets() for the proper test.
5519  if (elem->IsA() == TStreamerBase::Class()) {
5520  // -- This is a base class of cl.
5521  TClass* clOfBase = TClass::GetClass(elem->GetName());
5522  if ((clOfBase->Property() & kIsAbstract) && cl->InheritsFrom(TCollection::Class())) {
5523  // -- Do nothing if we are one of the abstract collection (we know they have no data).
5524  return -1;
5525  }
5526  if ((btype == 31) || (btype == 41)) {
5527  // -- Elide the base-class sub-branches of a split TClonesArray or STL container.
5528  //
5529  // Note: We are eliding the base class here, that is, we never
5530  // create a branch for it, so the branch heirarchy is not
5531  // complete.
5532  // Note: The clParent parameter is the value class of the
5533  // container which we are splitting. It does not
5534  // appear in the branch heirarchy either.
5535  // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
5536  Int_t unroll = -1;
5537  if (!elem->CannotSplit() || clOfBase == TObject::Class()) {
5538  unroll = Unroll(name, clParent, clOfBase, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5539  }
5540  if (unroll < 0) {
5541  // FIXME: We could not split because we are abstract, should we be doing this?
5542  if (strlen(name)) {
5543  branchname.Form("%s.%s", name, elem->GetFullName());
5544  } else {
5545  branchname.Form("%s", elem->GetFullName());
5546  }
5547  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, 0, btype);
5548  branch->SetParentClass(clParent);
5549  fBranches.Add(branch);
5550  }
5551  } else if (clOfBase->GetListOfRealData()->GetSize()) {
5552  // -- Create a branch for a non-empty base class.
5553  if (strlen(name)) {
5554  branchname.Form("%s.%s", name, elem->GetFullName());
5555  // Elide the base class name when creating the sub-branches.
5556  // Note: The branch names for sub-branches of a base class branch
5557  // do not represent the full class heirarchy because we do
5558  // this, however it does keep the branch names for the
5559  // inherited data members simple.
5560  TBranchElement* branch = new TBranchElement(this, name, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5561  // Then reset it to the proper name.
5562  branch->SetName(branchname);
5563  branch->SetTitle(branchname);
5564  branch->SetParentClass(clParent);
5565  fBranches.Add(branch);
5566  } else {
5567  branchname.Form("%s", elem->GetFullName());
5568  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5569  branch->SetParentClass(clParent);
5570  fBranches.Add(branch);
5571  }
5572  }
5573  } else {
5574  // -- This is a data member of cl.
5575  if (strlen(name)) {
5576  branchname.Form("%s.%s", name, elem->GetFullName());
5577  } else {
5578  branchname.Form("%s", elem->GetFullName());
5579  }
5580  if ((splitlevel > 1) && ((elem->IsA() == TStreamerObject::Class()) || (elem->IsA() == TStreamerObjectAny::Class()))) {
5581  // -- We are splitting a non-TClonesArray (may inherit from TClonesArray though), non-STL container object.
5582  //
5583  // Ignore an abstract class.
5584  // FIXME: How could an abstract class get here?
5585  // Partial answer: It is a base class. But this is a data member!
5586  TClass* elemClass = TClass::GetClass(elem->GetTypeName());
5587  if (elemClass->Property() & kIsAbstract) {
5588  return -1;
5589  }
5590  if (elem->CannotSplit()) {
5591  // We are not splitting.
5592  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
5593  branch->SetParentClass(clParent);
5594  fBranches.Add(branch);
5595  } else if (elemClass->InheritsFrom(TClonesArray::Class())) {
5596  // Splitting something derived from TClonesArray.
5597  Int_t subSplitlevel = splitlevel-1;
5598  if (btype == 31 || btype == 41 || elem->CannotSplit()) {
5599  // -- We split the sub-branches of a TClonesArray or an STL container only once.
5600  subSplitlevel = 0;
5601  }
5602  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel, btype);
5603  branch->SetParentClass(clParent);
5604  fBranches.Add(branch);
5605  } else {
5606  // Splitting a normal class.
5607  // FIXME: We are eliding the class we are splitting here,
5608  // i.e., we do not create a branch for it, so the
5609  // branch heirarchy does not match the class heirarchy.
5610  // Note: clParent is the class which contains a data member of
5611  // the class type which we are splitting.
5612  // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
5613  Int_t unroll = Unroll(branchname, clParent, elemClass, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
5614  if (unroll < 0) {
5615  // FIXME: We could not split because we are abstract, should we be doing this?
5616  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
5617  branch->SetParentClass(clParent);
5618  fBranches.Add(branch);
5619  }
5620  }
5621  }
5622  else if( elem->GetClassPointer() &&
5623  elem->GetClassPointer()->GetCollectionProxy() &&
5625  splitSTLP && fType != 4 )
5626  {
5627 
5628  TBranchSTL* branch = new TBranchSTL( this, branchname,
5630  basketsize, splitlevel - 1+splitSTLP, sinfo, elemID );
5631  branch->SetAddress( ptr+offset );
5632  fBranches.Add( branch );
5633  }
5634  else if ((elem->IsA() == TStreamerSTL::Class()) && !elem->IsaPointer()) {
5635  // -- We have an STL container.
5636  // Question: What if splitlevel == 0 here?
5637  // Answer: then we should not be here.
5638  Int_t subSplitlevel = splitlevel - 1;
5639  if ((btype == 31) || (btype == 41) || elem->CannotSplit()) {
5640  // -- We split the sub-branches of a TClonesArray or an STL container only once.
5641  subSplitlevel = 0;
5642  }
5643  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel+splitSTLP, btype);
5644  branch->SetParentClass(clParent);
5645  fBranches.Add(branch);
5646  } else if (((btype != 31) && (btype != 41)) && ptr && ((elem->GetClassPointer() == TClonesArray::Class()) || ((elem->IsA() == TStreamerSTL::Class()) && !elem->CannotSplit()))) {
5647  // -- We have a TClonesArray.
5648  // FIXME: We could get a ptr to a TClonesArray here by mistake.
5649  // Question: What if splitlevel == 0 here?
5650  // Answer: then we should not be here.
5651  // Note: ptr may be null in case of a TClonesArray inside another
5652  // TClonesArray or STL container, see the else clause.
5653  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
5654  branch->SetParentClass(clParent);
5655  fBranches.Add(branch);
5656  } else {
5657  // -- We are not going to split this element any farther.
5658  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, splitSTLP, btype);
5659  branch->SetType(btype);
5660  branch->SetParentClass(clParent);
5661  fBranches.Add(branch);
5662  }
5663  }
5664  }
5665 
5666  return 1;
5667 }
5668 
5669 ////////////////////////////////////////////////////////////////////////////////
5670 /// Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
5671 /// with the current value of fTree->GetCurrentFile unless this branch has been
5672 /// redirected to a different file. Also update the sub-branches.
5673 
5675 {
5676  // The BranchCount and BranchCount2 are part of higher level branches' list of
5677  // branches.
5678  // if (fBranchCount) fBranchCount->UpdateFile();
5679  // if (fBranchCount2) fBranchCount2->UpdateFile();
5681 }
const int ndata
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
TClassRef fTargetClass
! Reference to the target in-memory class
Long64_t GetReadEntry() const
Definition: TBranch.h:170
virtual Int_t GetEntries() const
Definition: TCollection.h:92
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
Int_t GetNdata() const
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:865
void FillLeavesAssociativeCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual void WriteFloat16(Float_t *f, TStreamerElement *ele=0)=0
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2551
An array of TObjects.
Definition: TObjArray.h:39
virtual void Print(Option_t *option="") const
Print branch parameters.
TBranchElement * fBranchCount2
pointer to secondary branchcount branch
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
virtual Int_t GetProperties() const
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
Int_t GetNelement() const
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Int_t * GetEntryOffset() const
Definition: TBasket.h:77
virtual void * GetValuePointer() const
Returns pointer to first data element of this branch.
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2663
T GetTypedValue(Int_t i, Int_t len, Bool_t subarr=kFALSE) const
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2229
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:51
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2068
void PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name &#39;searchname&#39;.
T GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const
Return value of element i in object at pointer.
Int_t fOffset
Offset of this branch.
Definition: TBranch.h:74
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
Int_t GetOffset() const
long long Long64_t
Definition: RtypesCore.h:69
Int_t GetID() const
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
const char * GetTypeName() const
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
virtual const char * GetName() const
Return name of this collection.
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
Bool_t IsReading() const
Definition: TBuffer.h:83
Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition: TBrowser.h:108
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
Int_t GetType() const
Definition: TDataType.h:70
Ssiz_t Length() const
Definition: TString.h:390
Long64_t fEntries
Number of entries.
Definition: TBranch.h:84
float Float_t
Definition: RtypesCore.h:53
virtual void InitInfo()
Init the streamer info for the branch class, try to compensate for class code unload/reload and schem...
float Size_t
Definition: RtypesCore.h:83
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)=0
const char Option_t
Definition: RtypesCore.h:62
virtual Bool_t CannotSplit() const
Returns true if the element cannot be split, false otherwise.
virtual Long64_t GetReadEntry() const
Definition: TTree.h:435
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
double T(double x)
Definition: ChebyshevPol.h:34
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
Double_t GetValue(Int_t i, Int_t len, Bool_t subarr=kFALSE) const
T GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
char * GetObject() const
Return a pointer to our object.
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
TString fParentName
Name of parent class.
virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=0)=0
ReadLeaves_t fReadLeaves
! Pointer to the ReadLeaves implementation to use.
Definition: TBranch.h:107
virtual void SetLeafCount(TLeaf *leaf)
Set the leaf count of this leaf.
Definition: TLeafElement.h:60
virtual void Reset(Option_t *option="")
Reset a Branch.
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5571
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
virtual void Commit(void *)=0
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name &#39;searchname&#39;.
Definition: TBranch.cxx:953
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1746
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5671
virtual EDataType GetType() const =0
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
void FillLeavesCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void SetName(const char *new_name)
Definition: TClassRef.h:70
Bool_t IsPersistent() const
Definition: TDataMember.h:89
const Int_t kBranchObject
Definition: TBranch.h:54
#define R__ASSERT(e)
Definition: TError.h:98
TClass * GetNewClass() const
#define gROOT
Definition: TROOT.h:364
void FillLeavesCustomStreamer(TBuffer &b)
Write leaves into i/o buffers for this branch.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3559
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
UInt_t fElemId
Identifier of the TStreamerElement.
TObjArray fBaskets
-> List of baskets of this branch
Definition: TBranch.h:90
Bool_t IsZombie() const
Definition: TObject.h:127
Bool_t IsMissingCollection() const
Detect a collection written using a zero pointer in old versions of root.
Basic string class.
Definition: TString.h:137
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method). ...
Definition: TClass.cxx:5580
virtual void SetAddress(void *addobj)
Point this branch at an object.
static void R__CleanName(std::string &name)
Remove trailing dimensions and make sure there is a trailing dot.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Long64_t GetDebugMin() const
Definition: TTree.h:390
const char * GetClassName()
Definition: TClassRef.h:74
virtual void Clear(const char *opt="")=0
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
virtual void ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t force)=0
void SetReadActionSequence()
Set the sequence of actions needed to read the data out of the buffer.
Int_t fNleaves
! Number of leaves
Definition: TBranch.h:78
void ReadLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
TObjArray fLeaves
-> List of leaves of this branch
Definition: TBranch.h:89
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
void MapObject(const TObject *obj, UInt_t offset=1)
Add object to the fMap container.
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
void PrintValue(Int_t i) const
Prints values of leaves.
TString & Prepend(const char *cs)
Definition: TString.h:604
Long64_t * fBasketSeek
[fMaxBaskets] Addresses of baskets on file
Definition: TBranch.h:93
const char * Class
Definition: TXMLSetup.cxx:64
UInt_t fCheckSum
CheckSum of class.
void FillLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void SetupAddressesImpl()
If the branch address is not set, we set all addresses starting with the top level parent branch...
TStreamerInfoActions::TActionSequence * fFillActionSequence
! Set of actions to be executed to write the data to the basket.
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
Bool_t fInit
! Initialization flag for branch assignment
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
virtual TClass * GetCollectionClass() const
virtual TObjArray * GetElements() const =0
void ReadLeavesClones(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t * fBasketBytes
[fMaxBaskets] Length of baskets on file
Definition: TBranch.h:91
virtual TList * GetBrowsables()
Returns (and, if 0, creates) browsable objects for this branch See TVirtualBranchBrowsable::FillListO...
Definition: TBranch.cxx:1170
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
Long64_t fEntryNumber
Current entry number (last one filled in this branch)
Definition: TBranch.h:73
void ReadLeavesCustomStreamer(TBuffer &b)
Read leaves into i/o buffers for this branch.
virtual const char * GetClonesName() const
TList * GetListOfRealData() const
Definition: TClass.h:405
void FillLeavesCollection(TBuffer &b)
Write leaves into i/o buffers for this branch.
const Int_t kBranchAny
Definition: TBranch.h:55
const char * Data() const
Definition: TString.h:349
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
void ReadLeavesMemberBranchCount(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t fWriteBasket
Last basket number written.
Definition: TBranch.h:72
Int_t fNdata
! Number of data in this branch
friend class TClonesArray
Definition: TObject.h:200
TVirtualArray * fOnfileObject
! Place holder for the onfile representation of data members.
Int_t GetOffset() const
Definition: TBranch.h:168
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
virtual Bool_t HasPointers() const =0
void SetFillActionSequence()
Set the sequence of actions needed to write the data out from the buffer.
TStreamerInfoActions::TActionSequence * fReadActionSequence
! Set of actions to be executed to extract the data from the basket.
virtual void SetAddress(void *addr)
We are the top level branch.
Definition: TBranchSTL.cxx:682
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
Int_t fMaximum
Maximum entries for a TClonesArray or variable array.
const char * GetCountName() const
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4702
void ReadLeavesCollectionSplitPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:907
void BuildTitle(const char *name)
Set branch and leaf name and title in the case of a container sub-branch.
virtual void ResetDeleteObject()
Release ownership of any allocated objects.
virtual TVirtualCollectionProxy * Generate() const =0
void FillLeavesClones(TBuffer &b)
Write leaves into i/o buffers for this branch.
void FillLeavesClonesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual void SetBasketSize(Int_t buffsize)
Reset the basket size for all sub-branches of this branch element.
void ReadLeavesMemberCounter(TBuffer &b)
Read leaves into i/o buffers for this branch.
virtual Bool_t IsaPointer() const
const Int_t kDoNotProcess
Definition: TBranch.h:52
virtual const char * GetParentName() const
T GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
TString & Append(const char *cs)
Definition: TString.h:492
Int_t * fBranchOffset
! Sub-Branch offsets with respect to current transient class
TVirtualCollectionProxy * fCollProxy
! collection interface (if any)
static const std::string pattern("pattern")
The addressing set have been called for this branch.
Long64_t GetEntries() const
Definition: TBranch.h:183
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode)...
virtual void Browse(TBrowser *b)
Browse the branch content.
Version_t fClassVersion
Version number of class.
TObjArray * GetListOfBranches()
Definition: TBranch.h:178
TClass * GetClass() const
Int_t fMaxBaskets
Maximum number of Baskets so far.
Definition: TBranch.h:75
void FillLeavesMemberCounter(TBuffer &b)
Write leaves into i/o buffers for this branch.
XFontStruct * id
Definition: TGX11.cxx:108
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
void FillLeavesMemberBranchCount(TBuffer &b)
Write leaves into i/o buffers for this branch.
TString fClassName
Class name of referenced object.
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of a BranchElement and return total number of bytes.
We are the owner of fOnfileObject.
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:124
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:33
void SetFillLeavesPtr()
Set the FillLeaves pointer to execute the expected operations.
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations)
Int_t GetClassVersion() const
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6613
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:6061
ROOT::ESTLType UnderlyingIsSTLCont(std::string_view type)
Return the type of STL collection, if any, that is the underlying type of the given type...
Int_t fSplitLevel
Branch split level.
Definition: TBranch.h:77
TString fClonesName
Name of class in TClonesArray (if any)
virtual void ResetAddress()
Set branch address to zero and free all allocated memory.
void ReadLeavesClonesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
A doubly linked list.
Definition: TList.h:47
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:1984
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4868
Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
virtual TFile * GetFile() const
Definition: TDirectory.h:155
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
void PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax=1000) const
print value of element i in object at pointer The function may be called in two ways: -method1 len < ...
virtual Int_t GetMaximum() const
Definition: TLeaf.h:76
virtual Int_t Fill()
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:737
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3276
void FillLeavesMakeClass(TBuffer &b)
Write leaves into i/o buffers for this branch.
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
void(TBranch::* ReadLeaves_t)(TBuffer &b)
Definition: TBranch.h:106
Int_t fID
element serial number in fInfo
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is &#39;source&#39;.
void SetParentClass(TClass *clparent)
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual void ls(Option_t *option="") const
Print the content of the element.
virtual Int_t Fill()
Loop on all leaves of this branch to fill the basket buffer.
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
Small helper class to generically acquire and release iterators.
Int_t fBasketSize
Initial Size of Basket Buffer.
Definition: TBranch.h:70
TObjArray * GetElements() const
void ReadLeavesCollection(TBuffer &b)
Read leaves into i/o buffers for this branch.
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:26
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4356
virtual void SetType(Int_t btype)
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)=0
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
const char * GetTypeNameBasic() const
Return type name of this element in case the type name is not a standard basic type, return the basic type name known to CINT.
Int_t GetLast() const
Definition: TBasket.h:81
TClassRef fParentClass
! Reference to class definition in fParentName
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for version number &#39;version&#39; to this clas...
Definition: TClass.cxx:6633
TDirectory * GetDirectory() const
Definition: TTree.h:391
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Bool_t IsFolder() const
Return kTRUE if more than one leaf, kFALSE otherwise.
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5059
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1551
UInt_t GetCheckSum() const
TBranchElement * fBranchCount
pointer to primary branchcount branch
Int_t fStreamerType
branch streamer type
TClass * GetParentClass()
Return a pointer to the parent class of the branch element.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
FillLeaves_t fFillLeaves
! Pointer to the FillLeaves implementation to use.
Definition: TBranch.h:109
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
TMarker * m
Definition: textangle.C:8
void SetReadLeavesPtr()
Set the ReadLeaves pointer to execute the expected operations.
const Handle_t kNone
Definition: GuiTypes.h:89
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()=0
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
void ReadLeavesImpl(TBuffer &b)
Unconfiguration Read Leave function.
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
void Init(TTree *tree, TBranch *parent, const char *name, TStreamerInfo *sinfo, Int_t id, char *pointer, Int_t basketsize=32000, Int_t splitlevel=0, Int_t btype=0)
Init when the branch object is not a TClonesArray nor an STL container.
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:380
short Short_t
Definition: RtypesCore.h:35
TClassRef fCurrentClass
! Reference to current (transient) class definition
virtual void * New() const
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:34
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1217
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:358
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
long double LongDouble_t
Definition: RtypesCore.h:57
TClassRef fBranchClass
! Reference to class definition in fClassName
void Print(Option_t *="") const
This method must be overridden when a class wants to print itself.
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:1572
Version_t GetClassVersion() const
Definition: TClass.h:382
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Bool_t forCollection)
We are the owner of fObject.
TString fName
Definition: TNamed.h:36
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual Int_t GetMaximum() const
Return maximum count value of the branchcount if any.
void ValidateAddress() const
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
virtual TClass * GetClass() const
TTree * GetTree() const
Definition: TBranch.h:184
A TLeaf for the general case when using the branches created via a TStreamerInfo (i.e.
Definition: TLeafElement.h:34
TStreamerInfo * GetInfoImp() const
Get streamer info for the branch class.
A Branch for the case of an object.
#define Printf
Definition: TGeoToOCC.h:18
Int_t GetCompressionSettings() const
Definition: TFile.h:372
virtual void SetRequestedEntry(Long64_t entry)
Definition: TBranchRef.h:55
PyObject * fType
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2115
virtual void ReadFloat16(Float_t *f, TStreamerElement *ele=0)=0
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process&#39;s memory.
Definition: TClass.cxx:5545
int Ssiz_t
Definition: RtypesCore.h:63
void SetBranchCount(TBranchElement *bre)
Set the branch counter for this branch.
virtual Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)=0
Int_t fSTLtype
! STL container type
const char * GetCountName() const
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual const char * GetTypeName() const
Return type name of element in the branch.
TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const
Return the StreamerElement of "datamember" inside our class or any of its base classes.
virtual TVirtualArray * PopDataCache()
Pop and Return the &#39;current&#39; data cache area from the list of area to be used for temporarily store &#39;...
Definition: TBuffer.cxx:350
T GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
#define ClassImp(name)
Definition: Rtypes.h:279
Int_t fReadBasket
! Current basket number when reading
Definition: TBranch.h:79
const char * GetIconName() const
Return icon name depending on type of branch element.
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2037
double Double_t
Definition: RtypesCore.h:55
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual TClass * GetValueClass() const =0
void FillLeavesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
TClass * GetClass() const
Definition: TClonesArray.h:57
Describe directory structure in memory.
Definition: TDirectory.h:44
int type
Definition: TGX11.cxx:120
unsigned long long ULong64_t
Definition: RtypesCore.h:70
unsigned long ULong_t
Definition: RtypesCore.h:51
void SetBranchCount2(TBranchElement *bre)
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:366
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Bool_t IsAutoDelete() const
Return kTRUE if an existing object in a TBranchObject must be deleted.
Definition: TBranch.cxx:1671
Int_t fBranchID
! ID number assigned by a TRefTable.
std::vector< Int_t > fIDs
! List of the serial number of all the StreamerInfo to be used.
EDataType
Definition: TDataType.h:30
TBranchElement()
Default and I/O constructor.
Int_t GetNewType() const
virtual void * At(UInt_t idx)=0
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2828
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual Int_t SetParent(const TObject *obj, Int_t branchID)
Set the current parent branch.
Definition: TBranchRef.cxx:212
#define R__LOCKGUARD(mutex)
TTree * fTree
! Pointer to Tree header
Definition: TBranch.h:94
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:179
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
virtual void PushDataCache(TVirtualArray *)
Push a new data cache area onto the list of area to be used for temporarily store &#39;missing&#39; data memb...
Definition: TBuffer.cxx:331
TDirectory * fDirectory
! Pointer to directory where this branch buffers are stored
Definition: TBranch.h:98
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2882
TCanvas * slash()
Definition: slash.C:1
const char * GetFileName() const
Definition: TBranch.h:167
TClassRef fClonesClass
! Reference to class definition in fClonesName
UInt_t GetCheckSum()
virtual void SetOffset(Int_t offset)
Set offset of the object (to which the data member represented by this branch belongs) inside its con...
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2811
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3222
void ReadLeavesMakeClass(TBuffer &b)
Read leaves into i/o buffers for this branch.
TClass * GetClass() const
Mother of all ROOT objects.
Definition: TObject.h:44
virtual void ReadDouble32(Double_t *d, TStreamerElement *ele=0)=0
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
TClass * GetClass() const
Definition: TClassRef.h:75
Bool_t fInitOffsets
! Initialization flag to not endlessly recalculate offsets
TClassRef is used to implement a permanent reference to a TClass object.
Definition: TClassRef.h:33
char Char_t
Definition: RtypesCore.h:29
An array of clone (identical) objects.
Definition: TClonesArray.h:32
Int_t GetType() const
Int_t Debug() const
Definition: TTree.h:364
Long64_t * fBasketEntry
[fMaxBaskets] Table of first entry in each basket
Definition: TBranch.h:92
virtual ~TBranchElement()
Destructor.
static void SwitchContainer(TObjArray *)
Modify the container type of the branches.
void FillLeavesCollectionSplitPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual void ExpandCreateFast(Int_t n)
Expand or shrink the array to n elements and create the clone objects by calling their default ctor...
virtual char * GetAddress() const
Get the branch address.
virtual void Add(TObject *obj)
Definition: TList.h:81
virtual TClass * GetClass() const =0
const Ssiz_t kNPOS
Definition: Rtypes.h:115
#define R__unlikely(expr)
Definition: RConfig.h:524
char * GetObjectAt(UInt_t ind) const
Definition: TVirtualArray.h:38
Int_t Length() const
Definition: TBuffer.h:96
virtual Int_t GetCollectionType() const =0
Int_t GetClassVersion()
virtual Int_t GetLenStatic() const
Definition: TLeaf.h:74
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:1943
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
void FillLeavesImpl(TBuffer &b)
Unconfiguration Fill Leave function.
virtual Bool_t IsWritable() const
Definition: TDirectory.h:171
TVirtualCollectionIterators * fWriteIterators
! holds the read (non-staging) iterators when the branch is of fType==4 and associative containers...
Int_t GetNevBufSize() const
Definition: TBasket.h:80
void(TBranch::* FillLeaves_t)(TBuffer &b)
Definition: TBranch.h:108
Long64_t fReadEntry
! Current entry number when reading
Definition: TBranch.h:80
Int_t fType
branch type
TVirtualCollectionIterators * fIterators
! holds the iterators when the branch is of fType==4.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
TBranch * fMother
! Pointer to top-level parent branch in the tree.
Definition: TBranch.h:95
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1841
TStreamerElement * GetElement(Int_t id) const
#define gPad
Definition: TVirtualPad.h:289
Int_t GetType() const
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2800
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:447
Definition: tree.py:1
void SetSize(UInt_t size)
Definition: TVirtualArray.h:40
void Add(TObject *obj)
Definition: TObjArray.h:75
char * fObject
! Pointer to object at *fAddress
A TTree object has a header with a name and a title.
Definition: TTree.h:98
Int_t fEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TBranch.h:71
double result[121]
TObject ** GetObjectRef() const
Definition: TObjArray.h:70
void ResetBit(UInt_t f)
Definition: TObject.h:158
unsigned char UChar_t
Definition: RtypesCore.h:34
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4598
Int_t GetMakeClass() const
Definition: TTree.h:423
Bool_t IsFolder() const
Return kTRUE if more than one leaf or browsables, kFALSE otherwise.
Definition: TBranch.cxx:1679
#define R__LOCKGUARD_IMT2(mutex)
Definition: first.py:1
TObjArray fBranches
-> List of Branches of this branch
Definition: TBranch.h:88
const int nn
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:540
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
A TTree is a list of TBranches.
Definition: TBranch.h:58
Abstract Interface class describing Streamer information for one class.
Int_t fCompress
Compression level and algorithm.
Definition: TBranch.h:69
const Bool_t kTRUE
Definition: Rtypes.h:91
Long_t GetThisOffset() const
Definition: TRealData.h:59
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
TString fFileName
Name of file where buffers are stored ("" if in same file as Tree header)
Definition: TBranch.h:99
Base class of the Configurations.
More explicit alias for kMakeClass.
void PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
virtual TStreamerElement * GetElement(Int_t id) const =0
TBranch * fParent
! Pointer to parent branch.
Definition: TBranch.h:96
TVirtualCollectionPtrIterators * fPtrIterators
! holds the iterators when the branch is of fType==4 and it is a split collection of pointers...
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition: TClass.cxx:2387
const Int_t n
Definition: legend1.C:16
TStreamerInfo * fInfo
! Pointer to StreamerInfo
void ReadLeavesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t GetStreamerType() const
char name[80]
Definition: TGX11.cxx:109
Int_t GetDefaultEntryOffsetLen() const
Definition: TTree.h:388
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
virtual void InitializeOffsets()
Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a containe...
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions(Bool_t forCollection)
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4439
virtual UInt_t Size() const =0
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:417
void ReadLeavesCollectionMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
Need to pushd/pop fOnfileObject.
void ReleaseObject()
Delete any object we may have allocated on a previous call to SetAddress.
virtual void SetAutoDelete(Bool_t autodel=kTRUE)
Set the automatic delete bit.
Definition: TBranch.cxx:2102
char * fAddress
! Address of 1st leaf (variable or object)
Definition: TBranch.h:97
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911