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