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 (