Logo ROOT   6.08/07
Reference Guide
TBranchElement.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Authors Rene Brun , Philippe Canal, Markus Frank 14/01/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TBranchElement
13 \ingroup tree
14 
15 A Branch for the case of an object.
16 */
17 
18 #include "TBranchElement.h"
19 
20 #include "TBasket.h"
21 #include "TBranchObject.h"
22 #include "TBranchRef.h"
23 #include "TBrowser.h"
24 #include "TClass.h"
25 #include "TClassEdit.h"
26 #include "TClonesArray.h"
27 #include "TDataMember.h"
28 #include "TDataType.h"
29 #include "TError.h"
30 #include "TMath.h"
31 #include "TFile.h"
32 #include "TFolder.h"
33 #include "TLeafElement.h"
34 #include "TRealData.h"
35 #include "TStreamerElement.h"
36 #include "TStreamerInfo.h"
37 #include "TTree.h"
40 #include "TVirtualMutex.h"
41 #include "TVirtualPad.h"
42 #include "TBranchSTL.h"
43 #include "TVirtualArray.h"
44 #include "TBufferFile.h"
45 #include "TInterpreter.h"
46 #include "TROOT.h"
47 
48 #include "TStreamerInfoActions.h"
49 #include "TSchemaRuleSet.h"
50 
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 
55 namespace {
56  void RemovePrefix(TString& str, const char* prefix) {
57  // -- Remove a prefix from a string.
58  if (str.Length() && prefix && strlen(prefix)) {
59  if (!str.Index(prefix)) {
60  str.Remove(0, strlen(prefix));
61  }
62  }
63  }
64  struct R__PushCache {
65  TBufferFile &fBuffer;
66  TVirtualArray *fOnfileObject;
67 
68  R__PushCache(TBufferFile &b, TVirtualArray *in, UInt_t size) : fBuffer(b), fOnfileObject(in) {
69  if (fOnfileObject) {
70  fOnfileObject->SetSize(size);
71  fBuffer.PushDataCache( fOnfileObject );
72  }
73  }
74  ~R__PushCache() {
75  if (fOnfileObject) fBuffer.PopDataCache();
76  }
77  };
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// Modify the container type of the branches
82 
84  const Int_t nbranches = branches->GetEntriesFast();
85  for (Int_t i = 0; i < nbranches; ++i) {
86  TBranchElement* br = (TBranchElement*) branches->At(i);
87  switch (br->GetType()) {
88  case 31: br->SetType(41); break;
89  case 41: {
90  br->SetType(31);
91  br->fCollProxy = 0;
92  break;
93  }
94  }
95  br->SetReadLeavesPtr();
96  br->SetFillLeavesPtr();
97  // Note: This is a tail recursion.
98  SwitchContainer(br->GetListOfBranches());
99  }
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 
104 namespace {
105  Bool_t CanSelfReference(TClass *cl) {
106  if (cl) {
107  if (cl->GetCollectionProxy()) {
108  TClass *inside = cl->GetCollectionProxy()->GetValueClass();
109  if (inside) {
110  return CanSelfReference(inside);
111  } else {
112  return kFALSE;
113  }
114  }
115  const static TClassRef stringClass("std::string");
116  if (cl == stringClass || cl == TString::Class()) {
117  return kFALSE;
118  }
119  // Here we could scan through the TStreamerInfo to see if there
120  // is any pointer anywhere and know whether this is a possibility
121  // of selfreference (but watch out for very indirect cases).
122  return kTRUE;
123  }
124  return kFALSE;
125  }
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Default and I/O constructor.
130 
132 : TBranch()
133 , fClassName()
134 , fParentName()
135 , fClonesName()
136 , fCollProxy(0)
137 , fCheckSum(0)
138 , fClassVersion(0)
139 , fID(0)
140 , fType(0)
141 , fStreamerType(-1)
142 , fMaximum(0)
143 , fSTLtype(ROOT::kNotSTL)
144 , fNdata(1)
145 , fBranchCount(0)
146 , fBranchCount2(0)
147 , fInfo(0)
148 , fObject(0)
149 , fOnfileObject(0)
150 , fInit(kFALSE)
151 , fInitOffsets(kFALSE)
152 , fTargetClass()
153 , fCurrentClass()
154 , fParentClass()
155 , fBranchClass()
156 , fClonesClass()
157 , fBranchOffset(0)
158 , fBranchID(-1)
159 , fReadActionSequence(0)
160 , fFillActionSequence(0)
161 , fIterators(0)
162 , fWriteIterators(0)
163 , fPtrIterators(0)
164 {
165  fNleaves = 0;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Constructor when the branch object is not a TClonesArray nor an STL container.
172 ///
173 /// If splitlevel > 0 this branch in turn is split into sub-branches.
174 
175 TBranchElement::TBranchElement(TTree *tree, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
176 : TBranch()
177 , fClassName(sinfo->GetName())
178 , fParentName()
179 , fClonesName()
180 , fCollProxy(0)
181 , fCheckSum(sinfo->GetCheckSum())
183 , fID(id)
184 , fType(0)
185 , fStreamerType(-1)
186 , fMaximum(0)
188 , fNdata(1)
189 , fBranchCount(0)
190 , fBranchCount2(0)
191 , fInfo(sinfo)
192 , fObject(0)
193 , fOnfileObject(0)
194 , fInit(kTRUE)
197 , fCurrentClass()
198 , fParentClass()
199 , fBranchClass(sinfo->GetClass())
200 , fClonesClass()
201 , fBranchOffset(0)
202 , fBranchID(-1)
205 , fIterators(0)
206 , fWriteIterators(0)
207 , fPtrIterators(0)
208 {
209  Init(tree, 0, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Constructor when the branch object is not a TClonesArray nor an STL container.
214 ///
215 /// If splitlevel > 0 this branch in turn is split into sub-branches.
216 
217 TBranchElement::TBranchElement(TBranch *parent, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
218 : TBranch()
219 , fClassName(sinfo->GetName())
220 , fParentName()
221 , fClonesName()
222 , fCollProxy(0)
223 , fCheckSum(sinfo->GetCheckSum())
225 , fID(id)
226 , fType(0)
227 , fStreamerType(-1)
228 , fMaximum(0)
230 , fNdata(1)
231 , fBranchCount(0)
232 , fBranchCount2(0)
233 , fInfo(sinfo)
234 , fObject(0)
235 , fOnfileObject(0)
236 , fInit(kTRUE)
239 , fCurrentClass()
240 , fParentClass()
241 , fBranchClass(sinfo->GetClass())
242 , fClonesClass()
243 , fBranchOffset(0)
244 , fBranchID(-1)
247 , fIterators(0)
248 , fWriteIterators(0)
249 , fPtrIterators(0)
250 {
251  Init(parent ? parent->GetTree() : 0, parent, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Init when the branch object is not a TClonesArray nor an STL container.
256 ///
257 /// If splitlevel > 0 this branch in turn is split into sub-branches.
258 
259 void TBranchElement::Init(TTree *tree, TBranch *parent,const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
260 {
261  TString name(bname);
262 
263  // Set our TNamed attributes.
264  SetName(name);
265  SetTitle(name);
266 
267  // Set our TBranch attributes.
268  fSplitLevel = splitlevel;
269  fTree = tree;
270  if (fTree == 0) return;
271  fMother = parent ? parent->GetMother() : this;
272  fParent = parent;
274  fFileName = "";
275 
276  // Clear the bit kAutoDelete to specify that when reading
277  // the object should not be deleted before calling Streamer.
278 
280 
283 
284  //---------------------------------------------------------------------------
285  // Handling the splitting of the STL collections of pointers
286  /////////////////////////////////////////////////////////////////////////////
287 
288  Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
289  splitlevel %= TTree::kSplitCollectionOfPointers;
290 
291  fCompress = -1;
292  if (fTree->GetDirectory()) {
293  TFile* bfile = fTree->GetDirectory()->GetFile();
294  if (bfile) {
296  }
297  }
298 
299  //
300  // Initialize streamer type and element.
301  //
302 
303  if (id > -1) {
304  // We are *not* a top-level branch.
305  TStreamerElement* element = sinfo->GetElement(id);
306  fStreamerType = element->GetType();
307  }
308 
309  //
310  // Handle varying-length datatypes by allocating an offsets array.
311  //
312  // The fBits part of a TObject is of varying length because the pidf
313  // is streamed only when the TObject is referenced by a TRef.
314  //
315 
316  fEntryOffsetLen = 0;
319  }
320 
321  //
322  // Make sure the basket is big enough to contain the
323  // entry offset array plus 100 bytes of data.
324  //
325 
326  if (basketsize < (100 + fEntryOffsetLen)) {
327  basketsize = 100 + fEntryOffsetLen;
328  }
329  fBasketSize = basketsize;
330 
331  //
332  // Allocate and initialize the basket control arrays.
333  //
334 
338 
339  for (Int_t i = 0; i < fMaxBaskets; ++i) {
340  fBasketBytes[i] = 0;
341  fBasketEntry[i] = 0;
342  fBasketSeek[i] = 0;
343  }
344 
345  // We need to keep track of the counter branch if we have
346  // one, since we cannot set it until we have created our
347  // leaf, which we do last.
348  TBranchElement* brOfCounter = 0;
349 
350  if (id < 0) {
351  // -- We are a top-level branch. Don't split a top-level branch, TTree::Bronch will do that work.
352  if (fBranchClass.GetClass()) {
353  Bool_t hasCustomStreamer = kFALSE;
354  Bool_t canSelfReference = CanSelfReference(fBranchClass);
355  if (fBranchClass.GetClass()->IsTObject()) {
356  if (canSelfReference) SetBit(kBranchObject);
358  } else {
359  if (canSelfReference) SetBit(kBranchAny);
361  }
362  if (hasCustomStreamer) {
363  fType = -1;
364  }
365  }
366  } else {
367  // -- We are a sub-branch of a split object.
368  TStreamerElement* element = sinfo->GetElement(id);
370  // -- If we are an object data member which inherits from TObject,
371  // flag it so that later during i/o we will register the object
372  // with the buffer so that pointers are handled correctly.
373  if (CanSelfReference(fBranchClass)) {
374  if (fBranchClass.GetClass()->IsTObject()) {
376  } else {
378  }
379  }
380  }
381  if (element->IsA() == TStreamerBasicPointer::Class()) {
382  // -- Fixup title with counter if we are a varying length array data member.
384  TString countname;
385  countname = bname;
386  Ssiz_t dot = countname.Last('.');
387  if (dot>=0) {
388  countname.Remove(dot+1);
389  } else {
390  countname = "";
391  }
392  countname += bp->GetCountName();
393  brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
394  countname.Form("%s[%s]",name.Data(),bp->GetCountName());
395  SetTitle(countname);
396 
397  } else if (element->IsA() == TStreamerLoop::Class()) {
398  // -- Fixup title with counter if we are a varying length array data member.
399  TStreamerLoop *bp = (TStreamerLoop *)element;
400  TString countname;
401  countname = bname;
402  Ssiz_t dot = countname.Last('.');
403  if (dot>=0) {
404  countname.Remove(dot+1);
405  } else {
406  countname = "";
407  }
408  countname += bp->GetCountName();
409  brOfCounter = (TBranchElement *)fTree->GetBranch(countname);
410  countname.Form("%s[%s]",name.Data(),bp->GetCountName());
411  SetTitle(countname);
412 
413  }
414 
415  if (splitlevel > 0) {
416  // -- Create sub branches if requested by splitlevel.
417  const char* 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;
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::Fill();
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::Fill();
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->Fill();
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 
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  if (fType==31||fType==41) {
2038  // The nested objects are unfolded and their branch can not be used to
2039  // execute StreamerElements of this StreamerInfo.
2040  if (nextel->GetType() == TStreamerInfo::kObject
2041  || nextel->GetType() == TStreamerInfo::kAny) {
2042  continue;
2043  }
2044  }
2045  if (nextel->GetOffset() == TStreamerInfo::kMissing) {
2046  // This element will be 'skipped', it's TBranchElement's fObject will null
2047  // and thus can not be used to execute the artifical StreamerElements
2048  continue;
2049  }
2050  if (nextel->IsA() != TStreamerArtificial::Class()
2051  || nextel->GetType() == TStreamerInfo::kCacheDelete ) {
2052  break;
2053  }
2054  fIDs.push_back(i);
2055  }
2056  } else if (elt && offset==TStreamerInfo::kMissing) {
2057  // Still re-assign fID properly.
2058  fIDs.clear();
2059  size_t ndata = fInfo->GetNelement();
2060  for (size_t i = 0; i < ndata; ++i) {
2061  if (fInfo->GetElement(i) == elt) {
2062  fID = i;
2063  break;
2064  }
2065  }
2066  } else {
2067  // We have not even found the element .. this is strange :(
2068  // fIDs.clear();
2069  // fID = -3;
2070  // SetBit(kDoNotProcess);
2071  }
2072  if (fOnfileObject==0 && (fType==31 || fType==41 || (0 <= fType && fType <=2) ) && fInfo->GetNelement()
2074  {
2075  Int_t arrlen = 1;
2076  if (fType==31 || fType==41) {
2077  TLeaf *leaf = (TLeaf*)fLeaves.At(0);
2078  if (leaf) {
2079  arrlen = leaf->GetMaximum();
2080  }
2081  }
2082  fOnfileObject = new TVirtualArray( fInfo->GetElement(0)->GetClassPointer(), arrlen );
2083  // Propage this to all the other branch of this type.
2085  Int_t nbranches = branches->GetEntriesFast();
2086  TBranchElement *lastbranch = this;
2087  for (Int_t i = 0; i < nbranches; ++i) {
2088  TBranchElement* subbranch = (TBranchElement*)branches->At(i);
2089  if (this!=subbranch && subbranch->fBranchClass == fBranchClass && subbranch->fCheckSum == fCheckSum) {
2090  subbranch->fOnfileObject = fOnfileObject;
2091  lastbranch = subbranch;
2092  }
2093  }
2094  lastbranch->SetBit(kOwnOnfileObj);
2095  }
2096  }
2097  fInit = kTRUE;
2098 
2099  // Get the action sequence we need to copy for reading.
2102  } else if (!fReadActionSequence) {
2103  // Get the action sequence we need to copy for reading.
2106  }
2107  SetReadLeavesPtr();
2108  SetFillLeavesPtr();
2109  }
2110 }
2111 
2112 ////////////////////////////////////////////////////////////////////////////////
2113 /// Return the collection proxy describing the branch content, if any.
2114 
2116 {
2117  if (fCollProxy) {
2118  return fCollProxy;
2119  }
2120  TBranchElement* thiscast = const_cast<TBranchElement*>(this);
2121  if (fType == 4) {
2122  // STL container top-level branch.
2123  const char* className = 0;
2124  TClass* cl = nullptr;
2125  if (fID < 0) {
2126  // We are a top-level branch.
2127  if (fBranchClass.GetClass()) {
2128  cl = fBranchClass.GetClass();
2129  }
2130  } else {
2131  // We are not a top-level branch.
2132  TVirtualStreamerInfo* si = thiscast->GetInfoImp();
2133  TStreamerElement* se = si->GetElement(fID);
2134  cl = se->GetClassPointer();
2135  }
2136  if (!cl) {
2137  // The TClass was not created but we do know (since it
2138  // is used as a collection) that it 'className' was a
2139  // class, so let's create it by hand!.
2140 
2141  if (fID < 0) {
2144  className = cl->GetName();
2145  } else {
2146  cl = new TClass(className, fClassVersion);
2148  className = cl->GetName();
2149  }
2150  }
2152  if (!proxy) {
2153  // humm, we must have an older file with a custom collection
2154  // let's try to work-around it.
2155  TString equiv;
2156  equiv.Form("vector<%s>",fClonesName.Data());
2157  TClass *clequiv = TClass::GetClass(equiv);
2158  proxy = clequiv->GetCollectionProxy();
2159  if (!proxy) {
2160  Fatal("GetCollectionProxy",
2161  "Can not create a Collection Proxy of any kind for the class \"%s\" needed by the branch \"%s\" of the TTree \"%s\"!",
2162  className, GetName(), GetTree()->GetName());
2163  }
2164  if (gDebug > 0) Info("GetCollectionProxy",
2165  "Fixing the collection proxy of the class \"%s\" \n"
2166  "\tneeded by the branch \"%s\" of the TTree \"%s\" to be similar to \"%s\".",
2167  className, GetName(), GetTree()->GetName(),equiv.Data());
2168  cl->CopyCollectionProxy( *proxy );
2169  }
2170  fCollProxy = proxy->Generate();
2171  fSTLtype = proxy->GetCollectionType();
2172  } else if (fType == 41) {
2173  // STL container sub-branch.
2175  }
2176  return fCollProxy;
2177 }
2178 
2179 ////////////////////////////////////////////////////////////////////////////////
2180 /// Return a pointer to the current type of the data member corresponding to branch element.
2181 
2183 {
2184  TClass* cl = fCurrentClass;
2185  if (cl) {
2186  return cl;
2187  }
2188 
2189  TStreamerInfo* brInfo = (TStreamerInfo*)GetInfoImp();
2190  if (!brInfo) {
2192  R__ASSERT(cl && cl->GetCollectionProxy());
2193  fCurrentClass = cl;
2194  return cl;
2195  }
2196  TClass* motherCl = brInfo->GetClass();
2197  if (motherCl->GetCollectionProxy()) {
2198  cl = motherCl->GetCollectionProxy()->GetCollectionClass();
2199  if (cl) {
2200  fCurrentClass = cl;
2201  }
2202  return cl;
2203  }
2204  if (GetID() < 0 || GetID()>=brInfo->GetNelement()) {
2205  return 0;
2206  }
2207  TStreamerElement* currentStreamerElement = brInfo->GetElement(GetID());
2208  TDataMember* dm = (TDataMember*) motherCl->GetListOfDataMembers()->FindObject(currentStreamerElement->GetName());
2209 
2210  TString newType;
2211  if (!dm) {
2212  // Either the class is not loaded or the data member is gone
2213  if (!motherCl->IsLoaded()) {
2214  TVirtualStreamerInfo* newInfo = motherCl->GetStreamerInfo();
2215  if (newInfo != brInfo) {
2216  TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(currentStreamerElement->GetName());
2217  if (newElems) {
2218  if (newElems->GetClassPointer())
2219  newType = newElems->GetClassPointer()->GetName();
2220  else
2221  newType = newElems->GetTypeName();
2222  }
2223  }
2224  if (newType.Length()==0) {
2225  if (currentStreamerElement->GetClassPointer())
2226  newType = currentStreamerElement->GetClassPointer()->GetName();
2227  else
2228  newType = currentStreamerElement->GetTypeName();
2229  }
2230  }
2231  } else {
2232  newType = dm->GetTypeName();
2233  }
2234  cl = TClass::GetClass(newType);
2235  if (cl) {
2236  fCurrentClass = cl;
2237  }
2238  return cl;
2239 }
2240 
2241 ////////////////////////////////////////////////////////////////////////////////
2242 /// Read all branches of a BranchElement and return total number of bytes.
2243 ///
2244 /// - If entry = 0, then use current entry number + 1.
2245 /// - If entry < 0, then reset entry number to 0.
2246 ///
2247 /// Returns the number of bytes read from the input buffer.
2248 /// - If entry does not exist, then returns 0.
2249 /// - If an I/O error occurs, then returns -1.
2250 ///
2251 /// See IMPORTANT REMARKS in TTree::GetEntry.
2252 
2254 {
2255  // Remember which entry we are reading.
2256  fReadEntry = entry;
2257 
2258  // If our tree has a branch ref, make it remember the entry and
2259  // this branch. This allows a TRef::GetObject() call done during
2260  // the following I/O operation, for example in a custom streamer,
2261  // to search for the referenced object in the proper element of the
2262  // proper branch.
2263  TBranchRef* bref = fTree->GetBranchRef();
2264  if (R__unlikely(bref)) {
2265  R__LOCKGUARD_IMT2(gROOTMutex); // Lock for parallel TTree I/O
2266  fBranchID = bref->SetParent(this, fBranchID);
2267  bref->SetRequestedEntry(entry);
2268  }
2269 
2270  Int_t nbytes = 0;
2271 
2272  if (R__unlikely(IsAutoDelete())) {
2275  } else {
2276  if (R__unlikely(!fAddress && !fTree->GetMakeClass())) {
2277  R__LOCKGUARD_IMT2(gROOTMutex); // Lock for parallel TTree I/O
2279  }
2280  }
2281 
2282  Int_t nbranches = fBranches.GetEntriesFast();
2283  if (nbranches) {
2284  // -- Branch has daughters.
2285  // One must always read the branch counter.
2286  // In the case when one reads consecutively twice the same entry,
2287  // the user may have cleared the TClonesArray between the GetEntry calls.
2288  if ((fType == 3) || (fType == 4)) {
2289  Int_t nb = TBranch::GetEntry(entry, getall);
2290  if (nb < 0) {
2291  return nb;
2292  }
2293  nbytes += nb;
2294  }
2295  switch(fSTLtype) {
2296  case ROOT::kSTLset:
2297  case ROOT::kSTLmultiset:
2300  case ROOT::kSTLmap:
2301  case ROOT::kSTLmultimap:
2304  break;
2305  default:
2306  ValidateAddress(); // There is no ReadLeave for this node, so we need to do the validation here.
2307  for (Int_t i = 0; i < nbranches; ++i) {
2308  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
2309  Int_t nb = branch->GetEntry(entry, getall);
2310  if (nb < 0) {
2311  return nb;
2312  }
2313  nbytes += nb;
2314  }
2315  break;
2316  }
2317  } else {
2318  // -- Terminal branch.
2319  if (fBranchCount && (fBranchCount->GetReadEntry() != entry)) {
2320  Int_t nb = fBranchCount->TBranch::GetEntry(entry, getall);
2321  if (nb < 0) {
2322  return nb;
2323  }
2324  nbytes += nb;
2325  }
2326  Int_t nb = TBranch::GetEntry(entry, getall);
2327  if (nb < 0) {
2328  return nb;
2329  }
2330  nbytes += nb;
2331  }
2332 
2333  if (R__unlikely(fTree->Debug() > 0)) {
2334  if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
2335  Info("GetEntry", "%lld, branch=%s, nbytes=%d", entry, GetName(), nbytes);
2336  }
2337  }
2338  return nbytes;
2339 }
2340 
2341 ////////////////////////////////////////////////////////////////////////////////
2342 /// Fill expectedClass and expectedType with information on the data type of the
2343 /// object/values contained in this branch (and thus the type of pointers
2344 /// expected to be passed to Set[Branch]Address
2345 /// return 0 in case of success and > 0 in case of failure.
2346 
2348 {
2349  expectedClass = 0;
2350  expectedType = kOther_t;
2351 
2353  if ((type == -1) || (fID == -1)) {
2354  expectedClass = fBranchClass;
2355  } else {
2356  // Case of an object data member. Here we allow for the
2357  // variable name to be ommitted. Eg, for Event.root with split
2358  // level 1 or above Draw("GetXaxis") is the same as Draw("fH.GetXaxis()")
2359  TStreamerElement* element = GetInfoImp()->GetElement(fID);
2360  if (element) {
2361  expectedClass = element->GetClassPointer();
2362  if (!expectedClass) {
2363  TDataType* data = gROOT->GetType(element->GetTypeNameBasic());
2364  if (!data) {
2365  Error("GetExpectedType", "Did not find the type number for %s", element->GetTypeNameBasic());
2366  return 1;
2367  } else {
2368  expectedType = (EDataType) data->GetType();
2369  }
2370  }
2371  } else {
2372  Error("GetExpectedType", "Did not find the type for %s",GetName());
2373  return 2;
2374  }
2375  }
2376  return 0;
2377 }
2378 
2379 ////////////////////////////////////////////////////////////////////////////////
2380 /// Return icon name depending on type of branch element.
2381 
2382 const char* TBranchElement::GetIconName() const
2383 {
2384  if (IsFolder()) {
2385  return "TBranchElement-folder";
2386  } else {
2387  return "TBranchElement-leaf";
2388  }
2389 }
2390 
2391 ////////////////////////////////////////////////////////////////////////////////
2392 /// Return whether this branch is in a mode where the object are decomposed
2393 /// or not (Also known as MakeClass mode).
2394 
2396 {
2397  return TestBit(kDecomposedObj); // Same as TestBit(kMakeClass)
2398 }
2399 
2400 ////////////////////////////////////////////////////////////////////////////////
2401 /// Return maximum count value of the branchcount if any.
2402 
2404 {
2405  if (fBranchCount) {
2406  return fBranchCount->GetMaximum();
2407  }
2408  return fMaximum;
2409 }
2410 
2411 ////////////////////////////////////////////////////////////////////////////////
2412 /// Return a pointer to our object.
2413 
2415 {
2416  ValidateAddress();
2417  return fObject;
2418 }
2419 
2420 ////////////////////////////////////////////////////////////////////////////////
2421 /// Return a pointer to the parent class of the branch element.
2422 
2424 {
2425  return fParentClass.GetClass();
2426 }
2427 
2428 ////////////////////////////////////////////////////////////////////////////////
2429 /// Return type name of element in the branch.
2430 
2431 const char* TBranchElement::GetTypeName() const
2432 {
2433  if (fType == 3 || fType == 4) {
2434  return "Int_t";
2435  }
2436  // FIXME: Use symbolic constants here.
2437  if ((fStreamerType < 1) || (fStreamerType > 59)) {
2438  if (fBranchClass.GetClass()) {
2439  if (fID>=0) {
2440  return GetInfoImp()->GetElement(fID)->GetTypeName();
2441  } else {
2442  return fBranchClass.GetClass()->GetName();
2443  }
2444  } else {
2445  return 0;
2446  }
2447  }
2448  const char *types[20] = {
2449  "",
2450  "Char_t",
2451  "Short_t",
2452  "Int_t",
2453  "Long_t",
2454  "Float_t",
2455  "Int_t",
2456  "char*",
2457  "Double_t",
2458  "Double32_t",
2459  "",
2460  "UChar_t",
2461  "UShort_t",
2462  "UInt_t",
2463  "ULong_t",
2464  "UInt_t",
2465  "Long64_t",
2466  "ULong64_t",
2467  "Bool_t",
2468  "Float16_t"
2469  };
2470  Int_t itype = fStreamerType % 20;
2471  return types[itype];
2472 }
2473 
2474 ////////////////////////////////////////////////////////////////////////////////
2475 
2476 template Double_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2477 template Long64_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2478 template LongDouble_t TBranchElement::GetTypedValue(Int_t j, Int_t len, Bool_t subarr) const;
2479 
2480 template <typename T>
2482 {
2483  // -- Returns the branch value.
2484  //
2485  // If the leaf is an array, j is the index in the array.
2486  //
2487  // If leaf is an array inside a TClonesArray, len should be the length
2488  // of the array.
2489  //
2490  // If subarr is true, then len is actually the index within the sub-array.
2491  //
2492 
2493  ValidateAddress();
2494 
2495  Int_t prID = fID;
2496  char *object = fObject;
2497  if (TestBit(kCache)) {
2498  if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
2499  prID = fID+1;
2500  } else if (fOnfileObject) {
2501  object = fOnfileObject->GetObjectAt(0);
2502  }
2503  }
2504 
2505  if (!j && fBranchCount) {
2506  Long64_t entry = fTree->GetReadEntry();
2507  // Since reloading the index, will reset the ClonesArray, let's
2508  // skip the load if we already read this entry.
2509  if (entry != fBranchCount->GetReadEntry()) {
2510  fBranchCount->TBranch::GetEntry(entry);
2511  }
2512  if (fBranchCount2 && entry != fBranchCount2->GetReadEntry()) {
2513  fBranchCount2->TBranch::GetEntry(entry);
2514  }
2515  }
2516 
2517  if (fTree->GetMakeClass()) {
2518  if (!fAddress) {
2519  return 0;
2520  }
2521  if ((fType == 3) || (fType == 4)) {
2522  // Top-level branch of a TClonesArray.
2523  return fNdata;
2524  } else if ((fType == 31) || (fType == 41)) {
2525  // sub branch of a TClonesArray
2526  Int_t atype = fStreamerType;
2527  if (atype < 20) {
2528  atype += 20;
2529  }
2530  return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
2531  } else if (fType <= 2) {
2532  // branch in split mode
2533  // FIXME: This should probably be < 60 instead!
2534  if ((fStreamerType > 40) && (fStreamerType < 55)) {
2535  Int_t atype = fStreamerType - 20;
2536  return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
2537  } else {
2538  return GetInfoImp()->GetTypedValue<T>(object, prID, j, -1);
2539  }
2540  }
2541  }
2542 
2543  if (object == 0)
2544  {
2545  // We have nowhere to read the data from (probably because the data member was
2546  // 'dropped' from the current schema).
2547  return 0;
2548  }
2549 
2550  if (fType == 31) {
2551  TClonesArray* clones = (TClonesArray*) object;
2552  if (subarr) {
2553  return GetInfoImp()->GetTypedValueClones<T>(clones, prID, j, len, fOffset);
2554  }
2555  return GetInfoImp()->GetTypedValueClones<T>(clones, prID, j/len, j%len, fOffset);
2556  } else if (fType == 41) {
2559  {
2560  if (subarr)
2561  return GetInfoImp()->GetTypedValueSTL<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
2562 
2563  return GetInfoImp()->GetTypedValueSTL<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
2564  }
2565  else
2566  {
2567  if (subarr)
2568  return GetInfoImp()->GetTypedValueSTLP<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j, len, fOffset);
2569  return GetInfoImp()->GetTypedValueSTLP<T>(((TBranchElement*) this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
2570  }
2571  } else {
2572  if (GetInfoImp()) {
2573  return GetInfoImp()->GetTypedValue<T>(object, prID, j, -1);
2574  }
2575  return 0;
2576  }
2577 }
2578 
2579 ////////////////////////////////////////////////////////////////////////////////
2580 /// Returns pointer to first data element of this branch.
2581 /// Currently used only for members of type character.
2582 
2584 {
2585  ValidateAddress();
2586 
2587  Int_t prID = fID;
2588  char *object = fObject;
2589  if (TestBit(kCache)) {
2590  if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
2591  prID = fID+1;
2592  } else if (fOnfileObject) {
2593  object = fOnfileObject->GetObjectAt(0);
2594  }
2595  }
2596 
2597  if (fBranchCount) {
2598  Long64_t entry = fTree->GetReadEntry();
2599  fBranchCount->TBranch::GetEntry(entry);
2600  if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
2601  }
2602  if (fTree->GetMakeClass()) {
2603  if (!fAddress) {
2604  return 0;
2605  }
2606  if (fType == 3) { //top level branch of a TClonesArray
2607  //return &fNdata;
2608  return 0;
2609  } else if (fType == 4) { //top level branch of a TClonesArray
2610  //return &fNdata;
2611  return 0;
2612  } else if (fType == 31) { // sub branch of a TClonesArray
2613  //Int_t atype = fStreamerType;
2614  //if (atype < 20) atype += 20;
2615  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2616  return 0;
2617  } else if (fType == 41) { // sub branch of a TClonesArray
2618  //Int_t atype = fStreamerType;
2619  //if (atype < 20) atype += 20;
2620  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2621  return 0;
2622  } else if (fType <= 2) { // branch in split mode
2623  // FIXME: This should probably be < 60 instead!
2624  if (fStreamerType > 40 && fStreamerType < 55) {
2625  //Int_t atype = fStreamerType - 20;
2626  //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
2627  return 0;
2628  } else {
2629  //return GetInfoImp()->GetValue(object, fID, j, -1);
2630  return 0;
2631  }
2632  }
2633  }
2634 
2635  if (fType == 31) {
2636  return 0;
2637  } else if (fType == 41) {
2638  return 0;
2639  } else if (prID < 0) {
2640  return object;
2641  } else {
2642  //return GetInfoImp()->GetValue(object,fID,j,-1);
2643  if (!GetInfoImp() || !object) return 0;
2644  char **val = (char**)(object+GetInfoImp()->TStreamerInfo::GetElementOffset(prID));
2645  return *val;
2646  }
2647 }
2648 
2649 ////////////////////////////////////////////////////////////////////////////////
2650 /// Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a container sub-branch.
2651 ///
2652 /// Note: The offsets are zero for data members so that when
2653 /// SetAddress recursively sets their address, they will get the
2654 /// same address as their containing class because i/o is based
2655 /// on streamer info offsets from the addresss of the containing
2656 /// class.
2657 ///
2658 /// Offsets are non-zero for base-class sub-branches that are
2659 /// not the leftmost direct base class. They are laid out in
2660 /// memory sequentially and only the leftmost direct base class
2661 /// has the same address as the derived class. The streamer
2662 /// offsets need to be added to the address of the base class
2663 /// subobject which is not the same as the address of the
2664 /// derived class for the non-leftmost direct base classes.
2665 
2667 {
2668  Int_t nbranches = fBranches.GetEntriesFast();
2669 
2670  if (fID < 0) {
2671  // -- We are a top-level branch. Let's mark whether we need to use MapObject.
2672  if (CanSelfReference(fBranchClass)) {
2673  if (fBranchClass.GetClass()->IsTObject()) {
2675  } else {
2676  SetBit(kBranchAny);
2677  }
2678  }
2679  }
2680  if (nbranches) {
2681  // Allocate space for the new sub-branch offsets.
2682  delete[] fBranchOffset;
2683  fBranchOffset = 0;
2684  fBranchOffset = new Int_t[nbranches];
2685  // Make sure we can instantiate our class meta info.
2686  if (!fBranchClass.GetClass()) {
2687  Warning("InitializeOffsets", "No branch class set for branch: %s", GetName());
2688  fInitOffsets = kTRUE;
2689  return;
2690  }
2691  // Make sure we can instantiate our class streamer info.
2692  if (!GetInfoImp()) {
2693  Warning("InitializeOffsets", "No streamer info available for branch: %s of class: %s", GetName(), fBranchClass.GetClass()->GetName());
2694  fInitOffsets = kTRUE;
2695  return;
2696  }
2697 
2698  // Get the class we are a member of now (which is the
2699  // type of our containing subobject) and get our offset
2700  // inside of our containing subobject (our local offset).
2701  // Note: branchElem stays zero if we are a top-level branch,
2702  // we have to be careful about this later.
2703  TStreamerElement* branchElem = 0;
2704  Int_t localOffset = 0;
2705  TClass* branchClass = fBranchClass.GetClass();
2706  Bool_t renamed = kFALSE;
2707  if (fID > -1) {
2708  // -- Branch is *not* a top-level branch.
2709  // Instead of the streamer info class, we want the class of our
2710  // specific element in the streamer info. We could be a data
2711  // member of a base class or a split class, in which case our
2712  // streamer info will be for our containing sub-object, while
2713  // we are actually a different type.
2715  // Note: We tested to make sure the streamer info was available previously.
2716  if (!si->IsCompiled()) {
2717  Warning("InitializeOffsets", "Streamer info for branch: %s has no elements array!", GetName());
2718  fInitOffsets = kTRUE;
2719  return;
2720  }
2721  // FIXME: Check that fID is in range.
2722  branchElem = si->GetElement(fID);
2723  if (!branchElem) {
2724  Warning("InitializeOffsets", "Cannot get streamer element for branch: %s!", GetName());
2725  fInitOffsets = kTRUE;
2726  return;
2727  } else if (branchElem->TestBit(TStreamerElement::kRepeat)) {
2728  // If we have a repeating streamerElement, use the next
2729  // one as it actually hold the 'real' data member('s offset)
2730  if (si->GetElement(fID+1)) {
2731  branchElem = si->GetElement(fID+1);
2732  }
2733  }
2734  localOffset = branchElem->GetOffset();
2735  branchClass = branchElem->GetClassPointer();
2736  if (localOffset == TStreamerInfo::kMissing) {
2737  fObject = 0;
2738  } else {
2739  renamed = branchClass && branchElem->GetNewClass() && (branchClass != branchElem->GetNewClass());
2740  }
2741  } else {
2742  renamed = fTargetClass != fBranchClass;
2743  }
2744  if (!branchClass) {
2745  Error("InitializeOffsets", "Could not find class for branch: %s", GetName());
2746  fInitOffsets = kTRUE;
2747  return;
2748  }
2749 
2750  //------------------------------------------------------------------------
2751  // Extract the name of the STL branch in case it has been split.
2752  //////////////////////////////////////////////////////////////////////////
2753 
2754  TString stlParentName;
2755  Bool_t stlParentNameUpdated = kFALSE;
2756  if( fType == 4 )
2757  {
2758  TBranch *br = GetMother()->GetSubBranch( this );
2759  stlParentName = br->GetName();
2760  stlParentName.Strip( TString::kTrailing, '.' );
2761 
2762  // We may ourself contain the 'Mother' branch name.
2763  // To avoid code duplication, we delegate the removal
2764  // of the mother's name to the first sub-branch loop.
2765  }
2766 
2767  // Loop over our sub-branches and compute their offsets.
2768  for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
2769  bool alternateElement = false;
2770 
2771  fBranchOffset[subBranchIdx] = 0;
2772  TBranchElement* subBranch = dynamic_cast<TBranchElement*> (fBranches[subBranchIdx]);
2773  if (subBranch == 0) {
2774  // -- Skip sub-branches that are not TBranchElements.
2775  continue;
2776  }
2777 
2778  if (renamed) {
2779  if (subBranch->fBranchClass == branchClass) {
2780  if (branchElem) subBranch->SetTargetClass(branchElem->GetNewClass()->GetName());
2781  else subBranch->SetTargetClass(fTargetClass->GetName());
2782  }
2783  }
2784 
2785  TVirtualStreamerInfo* sinfo = subBranch->GetInfoImp();
2786  if (!sinfo) {
2787  Warning("InitializeOffsets", "No streamer info for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2788  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2789  continue;
2790  }
2791  if (!sinfo->IsCompiled()) {
2792  Warning("InitializeOffsets", "No elements array for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2793  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2794  continue;
2795  }
2796  // FIXME: Make sure subBranch->fID is in range.
2797  TStreamerElement* subBranchElement = sinfo->GetElement(subBranch->fID);
2798  if (!subBranchElement) {
2799  Warning("InitializeOffsets", "No streamer element for branch: %s subbranch: %s", GetName(), subBranch->GetName());
2800  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2801  continue;
2802  } else if (subBranchElement->TestBit(TStreamerElement::kRepeat)) {
2803  // If we have a repeating streamerElement, use the next
2804  // one as it actually hold the 'real' data member('s offset)
2805  if (sinfo->GetElement(subBranch->fID+1)) {
2806  subBranchElement = sinfo->GetElement(subBranch->fID+1);
2807  }
2808  } else if (subBranchElement->TestBit(TStreamerElement::kCache)) {
2809  // We have a cached item which is not a repeated but we might still
2810  // have some Actions triggered by a rule that affect real
2811  // data member(s).
2812  if (subBranch->fReadActionSequence && subBranch->fReadActionSequence->fActions.size() > 1) {
2813  typedef TStreamerInfoActions::ActionContainer_t::iterator iterator;
2814  iterator end = subBranch->fReadActionSequence->fActions.end();
2815  for(iterator iter = subBranch->fReadActionSequence->fActions.begin();
2816  iter != end; ++iter) {
2817  TStreamerInfoActions::TConfiguration *config = iter->fConfiguration;
2818  UInt_t id = config->fElemId;
2819  TStreamerElement *e = (TStreamerElement*)config->fInfo->GetElements()->At(id);
2820  if (e && !e->TestBit(TStreamerElement::kCache)) {
2821  subBranchElement = e;
2822  alternateElement = true;
2823  break;
2824  }
2825  }
2826  }
2827  }
2828 
2829  localOffset = subBranchElement->GetOffset();
2830  if (localOffset == TStreamerInfo::kMissing) {
2831  subBranch->fObject = 0;
2832  }
2833 
2834  {
2835  Int_t streamerType = subBranchElement->GetType();
2836  if (streamerType > TStreamerInfo::kObject
2837  && subBranch->GetListOfBranches()->GetEntries()==0
2838  && CanSelfReference(subBranchElement->GetClass()))
2839  {
2840  subBranch->SetBit(kBranchAny);
2841  } else {
2842  subBranch->ResetBit(kBranchAny);
2843  }
2844  }
2845 
2846  if (subBranchElement->GetNewType()<0) {
2847  subBranch->ResetBit(kBranchAny);
2848  subBranch->ResetBit(kBranchObject);
2849  }
2850 
2851  // Note: This call is expensive, do it only once.
2852  TBranch* mother = GetMother();
2853  if (!mother) {
2854  Warning("InitializeOffsets", "Branch '%s' has no mother!", GetName());
2855  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
2856  continue;
2857  }
2858  TString motherName(mother->GetName());
2859  Bool_t motherDot = kFALSE;
2860  if (motherName.Length() && strchr(motherName.Data(), '.')) {
2861  motherDot = kTRUE;
2862  }
2863  Bool_t motherDotAtEnd = kFALSE;
2864  if (motherName.Length() && (motherName[motherName.Length()-1] == '.')) {
2865  motherDotAtEnd = kTRUE;
2866  }
2867 
2868  Bool_t isBaseSubBranch = kFALSE;
2869  if ((subBranch->fType == 1) || (subBranchElement && subBranchElement->IsBase())) {
2870  // -- Base class sub-branch (1).
2871  //
2872  // Note: Our type will not be 1, even though we are
2873  // a base class branch, if we are not split (see the
2874  // constructor), or if we are an STL container master
2875  // branch and a base class branch at the same time
2876  // or an std::string.
2877  isBaseSubBranch = kTRUE;
2878  }
2879 
2880  Bool_t isContDataMember = kFALSE;
2881  if ((subBranch->fType == 31) || (subBranch->fType == 41)) {
2882  // -- Container data member sub-branch (31 or 41).
2883  isContDataMember = kTRUE;
2884  }
2885 
2886  // I am either a data member sub-branch (0), or a base class
2887  // sub-branch (1), or TClonesArray master sub-branch (3),
2888  // or an STL container master sub-branch (4), or TClonesArray
2889  // data member sub-branch (31), or an STL container data member
2890  // sub-branch (41).
2891  //
2892  // My parent branch is either a top-level branch ((0), fID==(-2,-1)),
2893  // or a base class sub-branch (1), or a split-class branch (2),
2894  // or a TClonesArray master branch (3), or an STL container
2895  // master branch (4).
2896  //
2897 
2898  //
2899  // We need to extract from our name the name
2900  // of the data member which contains us, so
2901  // that we may then do a by-name lookup in the
2902  // dictionary meta info of our parent class to
2903  // get our offset in our parent class.
2904  //
2905 
2906  // Get our name.
2907  TString dataName(subBranch->GetName());
2908  if (motherDotAtEnd) {
2909  // -- Remove the top-level branch name from our name.
2910  dataName.Remove(0, motherName.Length());
2911  // stlParentNameUpdated is false the first time in this loop.
2912  if (!stlParentNameUpdated && stlParentName.Length()) {
2913  stlParentName.Remove(0, motherName.Length());
2914  stlParentNameUpdated = kTRUE;
2915  }
2916  } else if (motherDot) {
2917  // -- Remove the top-level branch name from our name, folder case.
2918  //
2919  // Note: We are in the case where our mother was created
2920  // by the branch constructor which takes a folder
2921  // as an argument. The mother branch has internal
2922  // dots in its name to represent the folder heirarchy.
2923  // The TTree::Bronch() routine has handled us as a
2924  // special case, we must compensate.
2925  if ((fID < 0) && (subBranchElement->IsA() == TStreamerBase::Class())) {
2926  // -- Our name is the mother name, remove it.
2927  // Note: The test is our parent is a top-level branch
2928  // and our streamer is the base class streamer,
2929  // this matches the exact test in TTree::Bronch().
2930  if (dataName.Length() == motherName.Length()) {
2931  dataName.Remove(0, motherName.Length());
2932  // stlParentNameUpdated is false the first time in this loop.
2933  if (!stlParentNameUpdated && stlParentName.Length()) {
2934  stlParentName.Remove(0, motherName.Length());
2935  }
2936  }
2937  } else {
2938  // -- Remove the mother name and the dot.
2939  if (dataName.Length() > motherName.Length()) {
2940  dataName.Remove(0, motherName.Length() + 1);
2941  if (!stlParentNameUpdated && stlParentName.Length()) {
2942  stlParentName.Remove(0, motherName.Length());
2943  }
2944  }
2945  }
2946  }
2947  stlParentNameUpdated = kTRUE;
2948  if (isBaseSubBranch) {
2949  // -- Remove the base class name suffix from our name.
2950  // Note: The pattern is the name of the base class.
2951  TString pattern(subBranchElement->GetName());
2952  if (pattern.Length() <= dataName.Length()) {
2953  if (!strcmp(dataName.Data() + (dataName.Length() - pattern.Length()), pattern.Data())) {
2954  // The branch name contains the name of the base class in it.
2955  // This name is not reproduced in the sub-branches, so we need to
2956  // remove it.
2957  dataName.Remove(dataName.Length() - pattern.Length());
2958  }
2959  }
2960  // Remove any leading dot.
2961  if (dataName.Length()) {
2962  if (dataName[0] == '.') {
2963  dataName.Remove(0, 1);
2964  }
2965  }
2966  // Note: We intentionally leave any trailing dot
2967  // in our modified name here.
2968  }
2969 
2970  // Get our parent branch's name.
2971  TString parentName(GetName());
2972  if (motherDotAtEnd) {
2973  // -- Remove the top-level branch name from our parent's name.
2974  parentName.Remove(0, motherName.Length());
2975  } else if (motherDot) {
2976  // -- Remove the top-level branch name from our parent's name, folder case.
2977  //
2978  // Note: We are in the case where our mother was created
2979  // by the branch constructor which takes a folder
2980  // as an argument. The mother branch has internal
2981  // dots in its name to represent the folder heirarchy.
2982  // The TTree::Bronch() routine has handled us as a
2983  // special case, we must compensate.
2984  if ((fID > -1) && (mother == mother->GetSubBranch(this)) && (branchElem->IsA() == TStreamerBase::Class())) {
2985  // -- Our parent's name is the mother name, remove it.
2986  // Note: The test is our parent's parent is a top-level branch
2987  // and our parent's streamer is the base class streamer,
2988  // this matches the exact test in TTree::Bronch().
2989  if (parentName.Length() == motherName.Length()) {
2990  parentName.Remove(0, motherName.Length());
2991  }
2992  } else {
2993  // -- Remove the mother name and the dot.
2994  if (parentName.Length() > motherName.Length()) {
2995  parentName.Remove(0, motherName.Length() + 1);
2996  }
2997  }
2998  }
2999  // FIXME: Do we need to use the other tests for a base class here?
3000  if (fType == 1) {
3001  // -- Our parent is a base class sub-branch, remove the base class name suffix from its name.
3002  if (mother != mother->GetSubBranch(this)) {
3003  // -- My parent's parent is not a top-level branch.
3004  // Remove the base class name suffix from the parent name.
3005  // Note: The pattern is the name of the base class.
3006  // coverity[var_deref_model] branchElem is non zero here since fType==1 and thus fID > -1
3007  TString pattern(branchElem->GetName());
3008  if (pattern.Length() <= parentName.Length()) {
3009  if (!strcmp(parentName.Data() + (parentName.Length() - pattern.Length()), pattern.Data())) {
3010  // The branch name contains the name of the base class in it.
3011  // This name is not reproduced in the sub-branches, so we need to
3012  // remove it.
3013  parentName.Remove(parentName.Length() - pattern.Length());
3014  }
3015  }
3016  }
3017  // Note: We intentionally leave any trailing dots
3018  // in the modified parent name here.
3019  }
3020 
3021  // Remove the parent branch name part from our name,
3022  // but only if the parent branch is not a top-level branch.
3023  // FIXME: We should not assume parent name does not have length 0.
3024  if (fID > -1) {
3025  RemovePrefix(dataName, parentName);
3026  }
3027 
3028  // Remove any leading dot.
3029  if (dataName.Length()) {
3030  if (dataName[0] == '.') {
3031  dataName.Remove(0, 1);
3032  }
3033  }
3034 
3035  // Remove any trailing dot.
3036  if (dataName.Length()) {
3037  if (dataName[dataName.Length()-1] == '.') {
3038  dataName.Remove(dataName.Length() - 1, 1);
3039  }
3040  }
3041 
3042  //
3043  // Now that we have our data member name, find our offset
3044  // in our parent class.
3045  //
3046  // Note: Our data member name can have many dots in it
3047  // if branches were elided between our parent branch
3048  // and us by Unroll().
3049  //
3050  // FIXME: This may not work if our member name is ambiguous.
3051  //
3052 
3053  Int_t offset = 0;
3054  if (dataName.Length()) {
3055  // -- We have our data member name, do a lookup in the dictionary meta info of our parent class.
3056  // Get our parent class.
3057  TClass* pClass = 0;
3058  // First check whether this sub-branch is part of the 'cache' (because the data member it
3059  // represents is no longer in the current class layout.
3060  TStreamerInfo *subInfo = subBranch->GetInfoImp();
3061  //if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
3062  if (subBranchElement->TestBit(TStreamerElement::kCache)) {
3063  pClass = ((TStreamerElement*)subInfo->GetElements()->At(0))->GetClassPointer();
3064  }
3065  // FIXME: Do we need the other base class tests here?
3066  if (!pClass) {
3067  if (fType == 1) {
3068  // -- Parent branch is a base class branch.
3069  // FIXME: Is using branchElem here the right thing?
3070  pClass = branchElem->GetClassPointer();
3071  if (pClass->Property() & kIsAbstract) {
3072  // the class is abstract, let see if the
3073 
3074  TBranchElement *parent = (TBranchElement*)GetMother()->GetSubBranch(this);
3075  if (parent && parent != this && !parent->GetClass()->IsLoaded() ) {
3076  // Our parent's class is emulated and we represent an abstract class.
3077  // and the target class has not been set explicilty.
3078  TString target = pClass->GetName();
3079  target += "@@emulated";
3080 
3081  pClass = TClass::GetClass(target);
3082  }
3083  }
3084  } else {
3085  // -- Parent branch is *not* a base class branch.
3086  // FIXME: This sometimes returns a null pointer.
3087  pClass = subBranch->GetParentClass();
3088  }
3089  }
3090  if (!pClass) {
3091  // -- No parent class, fix it.
3092  // FIXME: This is probably wrong!
3093  // Assume parent class is our parent branch's clones class or value class.
3094  if (GetClonesName() && strlen(GetClonesName())) {
3095  pClass = fClonesClass;
3096  if (!pClass) {
3097  Warning("InitializeOffsets", "subBranch: '%s' has no parent class, and cannot get class for clones class: '%s'!", subBranch->GetName(), GetClonesName());
3098  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3099  continue;
3100  }
3101  Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3102  }
3104  pClass = fBranchCount->fCollProxy->GetValueClass();
3105  Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass ? pClass->GetName() : "unknowned class");
3106  }
3107  if (!pClass) {
3108  // -- Still no parent class, assume our parent class is our parent branch's class.
3109  // FIXME: This is probably wrong!
3110  pClass = branchClass;
3111  // FIXME: Enable this warning!
3112  //Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3113  }
3114  }
3115  if (renamed && pClass) {
3116  if (pClass == branchClass) {
3117  pClass = branchElem->GetNewClass();
3118  } else if (fCollProxy && pClass == branchClass->GetCollectionProxy()->GetValueClass()) {
3119  pClass = fCollProxy->GetValueClass();
3120  }
3121  }
3122 
3123  //------------------------------------------------------------------
3124  // If we have the are the sub-branch of the TBranchSTL, we need
3125  // to remove it's name to get the correct real data offsets
3126  ////////////////////////////////////////////////////////////////////
3127 
3128  if( dynamic_cast<TBranchSTL*>(fParent) && stlParentName.Length() )
3129  {
3130  if( !strncmp( stlParentName.Data(), dataName.Data(), stlParentName.Length()-1 )
3131  && dataName[ stlParentName.Length() ] == '.' )
3132  dataName.Remove( 0, stlParentName.Length()+1 );
3133  }
3134 
3135  // Find our offset in our parent class using
3136  // a lookup by name in the dictionary meta info
3137  // for our parent class.
3138 
3139  if (alternateElement) {
3140  Ssiz_t dotpos = dataName.Last('.');
3141  Ssiz_t endpos = dataName.Length();
3142  if (dotpos != kNPOS) ++dotpos; else dotpos = 0;
3143  dataName.Replace(dotpos,endpos-dotpos,subBranchElement->GetFullName());
3144  }
3145  TRealData* rd = pClass->GetRealData(dataName);
3146  if (rd && (!rd->TestBit(TRealData::kTransient) || alternateElement)) {
3147  // -- Data member exists in the dictionary meta info, get the offset.
3148  // If we are using an alternateElement, it is the target of a rule
3149  // and might be indeed transient.
3150  offset = rd->GetThisOffset();
3151  } else if (subBranchElement->TestBit(TStreamerElement::kWholeObject)) {
3152  // We are a rule with no specific target, it applies to the whole
3153  // object, let's set the offset to zero
3154  offset = 0;
3155  } else {
3156  // -- No dictionary meta info for this data member, it must no
3157  // longer exist
3158  if (fEntries == 0) {
3159  // ... unless we creating the branch in which case
3160  // we have an internal error.
3161  if (pClass->GetListOfRealData()->GetEntries() == 0) {
3162  // We are probably missing the ShowMember, let's
3163  // just issue an error.
3164  Error("InitializeOffsets",
3165  "Could not find the real data member '%s' when constructing the branch '%s' [Likely missing ShowMember].",
3166  dataName.Data(),GetName());
3167  } else if (subInfo && subInfo->GetClassVersion()!=subInfo->GetClass()->GetClassVersion()) {
3168  // In the case where we are cloning a TTree that was created with an older version of the layout, we may not
3169  // able to find all the members
3170  Info("InitializeOffsets",
3171  "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'. ",
3172  dataName.Data(),GetName());
3173  } else {
3174  // Something really bad happen.
3175  Fatal("InitializeOffsets",
3176  "Could not find the real data member '%s' when constructing the branch '%s' [Likely an internal error, please report to the developers].",
3177  dataName.Data(),GetName());
3178  }
3179  }
3180  localOffset = TStreamerInfo::kMissing;
3181  }
3182  } else {
3183  // -- We have no data member name, ok for a base class, not good otherwise.
3184  if (isBaseSubBranch) {
3185  // I am a direct base class of my parent class, my local offset is enough.
3186  } else {
3187  Warning("InitializeOffsets", "Could not find the data member name for branch '%s' with parent branch '%s', assuming offset is zero!", subBranch->GetName(), GetName());
3188  }
3189  }
3190 
3191  //
3192  // Ok, do final calculations for fOffset and fBranchOffset.
3193  //
3194 
3195  if (isContDataMember) {
3196  // -- Container data members set fOffset instead of fBranchOffset.
3197  // The fOffset is what should be added to the start of the entry
3198  // in the collection (i.e., its current absolute address) to find
3199  // the beginning of the data member described by the current branch.
3200  //
3201  // Compensate for the i/o routines adding our local offset later.
3202  if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
3203  subBranch->SetOffset(TStreamerInfo::kMissing);
3204  // We stil need to set fBranchOffset in the case of a missing
3205  // element so that SetAddress is (as expected) not called
3206  // recursively in this case.
3207  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3208  } else {
3209  if (isBaseSubBranch) {
3210  // The value of 'offset' for a base class does not include its
3211  // 'localOffset'.
3212  subBranch->SetOffset(offset);
3213  } else {
3214  // The value of 'offset' for a regular data member does include its
3215  // 'localOffset', we need to remove it explicitly.
3216  subBranch->SetOffset(offset - localOffset);
3217  }
3218  }
3219  } else {
3220  // -- Set fBranchOffset for sub-branch.
3221  Int_t isSplit = 0 != subBranch->GetListOfBranches()->GetEntriesFast();
3222  if (subBranch->fObject == 0 && localOffset == TStreamerInfo::kMissing) {
3223  // The branch is missing
3224  fBranchOffset[subBranchIdx] = TStreamerInfo::kMissing;
3225 
3226  } else if (isSplit) {
3227  if (isBaseSubBranch) {
3228  // We are split, so we need to add in our local offset
3229  // to get our absolute address for our children.
3230  fBranchOffset[subBranchIdx] = offset + localOffset;
3231  } else {
3232  // We are split so our offset will never be
3233  // used in an i/o, so we do not have to subtract
3234  // off our local offset like below.
3235  fBranchOffset[subBranchIdx] = offset;
3236  }
3237  } else {
3238  if (isBaseSubBranch) {
3239  // We are not split, so our local offset will be
3240  // added later by the i/o routines.
3241  fBranchOffset[subBranchIdx] = offset;
3242  } else {
3243  // Compensate for the fact that the i/o routines
3244  // are going to add my local offset later.
3245  fBranchOffset[subBranchIdx] = offset - localOffset;
3246  }
3247  }
3248  }
3249  }
3250  }
3251  else {
3252  if (fID > -1) {
3253  // Branch is *not* a top-level branch.
3254  // Let's check if the target member is still present in memory
3256  fObject = 0;
3257  }
3258  }
3259  }
3260  fInitOffsets = kTRUE;
3261 }
3262 
3263 ////////////////////////////////////////////////////////////////////////////////
3264 /// Return kTRUE if more than one leaf, kFALSE otherwise.
3265 
3267 {
3268  Int_t nbranches = fBranches.GetEntriesFast();
3269  if (nbranches >= 1) {
3270  return kTRUE;
3271  }
3272  TList* browsables = const_cast<TBranchElement*>(this)->GetBrowsables();
3273  return browsables && browsables->GetSize();
3274 }
3275 
3276 ////////////////////////////////////////////////////////////////////////////////
3277 /// Detect a collection written using a zero pointer in old versions of root.
3278 /// In versions of ROOT older than 4.00/03, if a collection (TClonesArray
3279 /// or STL container) was split but the pointer to the collection was zeroed
3280 /// out, nothing was saved. Hence there is no __easy__ way to detect the
3281 /// case. In newer versions, a zero is written so that a 'missing' collection
3282 /// appears to be an empty collection.
3283 
3285 {
3286  Bool_t ismissing = kFALSE;
3288  if (basket && fTree) {
3289  Long64_t entry = fTree->GetReadEntry();
3291  Long64_t last;
3292  if (fReadBasket == fWriteBasket) {
3293  last = fEntryNumber - 1;
3294  } else {
3295  last = fBasketEntry[fReadBasket+1] - 1;
3296  }
3297  Int_t* entryOffset = basket->GetEntryOffset();
3298  Int_t bufbegin;
3299  Int_t bufnext;
3300  if (entryOffset) {
3301  bufbegin = entryOffset[entry-first];
3302 
3303  if (entry < last) {
3304  bufnext = entryOffset[entry+1-first];
3305  } else {
3306  bufnext = basket->GetLast();
3307  }
3308  if (bufnext == bufbegin) {
3309  ismissing = kTRUE;
3310  } else {
3311  // fixed length buffer so this is not the case here.
3312  if (basket->GetNevBufSize() == 0) {
3313  ismissing = kTRUE;
3314  }
3315  }
3316  }
3317  }
3318  return ismissing;
3319 }
3320 
3321 ////////////////////////////////////////////////////////////////////////////////
3322 /// Print branch parameters.
3323 
3324 void TBranchElement::Print(Option_t* option) const
3325 {
3326  Int_t nbranches = fBranches.GetEntriesFast();
3327  if (strncmp(option,"debugAddress",strlen("debugAddress"))==0) {
3328  if (strlen(option)==strlen("debugAddress")) {
3329  Printf("%-24s %-16s %2s %4s %-16s %-16s %8s %8s %s\n",
3330  "Branch Name", "Streamer Class", "ID", "Type", "Class", "Parent", "pOffset", "fOffset", "fObject");
3331  }
3332  if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
3333  else Printf("%-24s ", GetName());
3334 
3335  TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
3336  Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
3337  TVirtualStreamerInfo *info = ((TBranchElement*)this)->GetInfoImp();
3338 
3339  Printf("%-16s %2d %4d %-16s %-16s %8x %8x %s\n",
3340  info ? info->GetName() : "StreamerInfo unvailable", GetID(), GetType(),
3342  (fBranchOffset&&parent && ind>=0) ? parent->fBranchOffset[ind] : 0,
3343  GetOffset(), GetObject());
3344  for (Int_t i = 0; i < nbranches; ++i) {
3345  TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
3346  subbranch->Print("debugAddressSub");
3347  }
3348  return;
3349  }
3350  if (strncmp(option,"debugInfo",strlen("debugInfo"))==0) {
3351  Printf("Branch %s uses:",GetName());
3352  if (fID>=0) {
3353  GetInfoImp()->GetElement(fID)->ls();
3354  for(UInt_t i=0; i< fIDs.size(); ++i) {
3355  GetInfoImp()->GetElement(fIDs[i])->ls();
3356  }
3357  Printf(" with read actions:");
3359  Printf(" with write actions:");
3361  }
3362  TString suboption = "debugInfoSub";
3363  suboption += (option+strlen("debugInfo"));
3364  for (Int_t i = 0; i < nbranches; ++i) {
3365  TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
3366  subbranch->Print(suboption);
3367  }
3368  Printf(" ");
3369  return;
3370  }
3371  if (nbranches) {
3372  if (fID == -2) {
3373  if (strcmp(GetName(),GetTitle()) == 0) {
3374  Printf("*Branch :%-66s *",GetName());
3375  } else {
3376  Printf("*Branch :%-9s : %-54s *",GetName(),GetTitle());
3377  }
3378  Printf("*Entries : %8d : BranchElement (see below) *",Int_t(fEntries));
3379  Printf("*............................................................................*");
3380  }
3381  if (fType >= 2) {
3382  TBranch::Print(option);
3383  }
3384  for (Int_t i=0;i<nbranches;i++) {
3385  TBranch *branch = (TBranch*)fBranches.At(i);
3386  branch->Print(option);
3387  }
3388  } else {
3389  TBranch::Print(option);
3390  }
3391 }
3392 
3393 ////////////////////////////////////////////////////////////////////////////////
3394 /// Prints values of leaves.
3395 
3397 {
3398  ValidateAddress();
3399 
3400  TStreamerInfo *info = GetInfoImp();
3401  Int_t prID = fID;
3402  char *object = fObject;
3403  if (TestBit(kCache)) {
3405  prID = fID+1;
3406  } else if (fOnfileObject) {
3407  object = fOnfileObject->GetObjectAt(0);
3408  }
3409  }
3410 
3411  if (fTree->GetMakeClass()) {
3412  if (!fAddress) {
3413  return;
3414  }
3415  if (fType == 3 || fType == 4) {
3416  // TClonesArray or STL container top-level branch.
3417  printf(" %-15s = %d\n", GetName(), fNdata);
3418  return;
3419  } else if (fType == 31 || fType == 41) {
3420  // TClonesArray or STL container sub-branch.
3421  Int_t n = TMath::Min(10, fNdata);
3424  // TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar is
3425  // printed as a string and could print weird characters.
3426  // So we print an unsigned char instead (not perfect, but better).
3427  atype = TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar;
3428  }
3429  if (atype > 54) {
3430  // FIXME: More logic required here (like in ReadLeaves)
3431  printf(" %-15s = %d\n", GetName(), fNdata);
3432  return;
3433  }
3434  if (fStreamerType > 20) {
3435  atype -= 20;
3437  n = n * leaf->GetLenStatic();
3438  }
3439  if (GetInfoImp()) {
3440  GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
3441  }
3442  return;
3443  } else if (fType <= 2) {
3444  // Branch in split mode.
3445  // FIXME: This should probably be < 60 instead.
3446  if ((fStreamerType > 40) && (fStreamerType < 55)) {
3447  Int_t atype = fStreamerType - 20;
3448  TBranchElement* counterElement = (TBranchElement*) fBranchCount;
3449  Int_t n = (Int_t) counterElement->GetValue(0, 0);
3450  if (GetInfoImp()) {
3451  GetInfoImp()->PrintValue(GetName(), fAddress, atype, n, lenmax);
3452  }
3453  } else {
3454  if (GetInfoImp()) {
3455  GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
3456  }
3457  }
3458  return;
3459  }
3460  } else if (fType == 3) {
3461  printf(" %-15s = %d\n", GetName(), fNdata);
3462  } else if (fType == 31) {
3463  TClonesArray* clones = (TClonesArray*) object;
3464  if (GetInfoImp()) {
3465  GetInfoImp()->PrintValueClones(GetName(), clones, prID, fOffset, lenmax);
3466  }
3467  } else if (fType == 41) {
3469  if (GetInfoImp()) {
3470  GetInfoImp()->PrintValueSTL(GetName(), ((TBranchElement*) this)->GetCollectionProxy(), prID, fOffset, lenmax);
3471  }
3472  } else {
3473  if (GetInfoImp()) {
3474  GetInfoImp()->PrintValue(GetName(), object, prID, -1, lenmax);
3475  }
3476  }
3477 }
3478 
3479 ////////////////////////////////////////////////////////////////////////////////
3480 /// Unconfiguration Read Leave function.
3481 
3483 {
3484  Fatal("ReadLeaves","The ReadLeaves function has not been configured for %s",GetName());
3485 }
3486 
3487 ////////////////////////////////////////////////////////////////////////////////
3488 /// Read leaves into i/o buffers for this branch.
3489 /// For the case where the branch is set in MakeClass mode (decomposed object).
3490 
3492 {
3493  ValidateAddress();
3494 
3495  if (fType == 3 || fType == 4) {
3496  // Top level branch of a TClonesArray.
3497  Int_t *n = (Int_t*) fAddress;
3498  b >> n[0];
3499  if ((n[0] < 0) || (n[0] > fMaximum)) {
3500  if (IsMissingCollection()) {
3501  n[0] = 0;
3502  b.SetBufferOffset(b.Length() - sizeof(n));
3503  } else {
3504  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());
3505  n[0] = 0;
3506  }
3507  }
3508  fNdata = n[0];
3509  if (fType == 4) {
3510  Int_t nbranches = fBranches.GetEntriesFast();
3511  switch(fSTLtype) {
3512  case ROOT::kSTLset:
3513  case ROOT::kSTLmultiset:
3514  case ROOT::kSTLmap:
3515  case ROOT::kSTLmultimap:
3516  for (Int_t i=0; i<nbranches; i++) {
3517  TBranch *branch = (TBranch*)fBranches[i];
3518  Int_t nb = branch->GetEntry(GetReadEntry(), 1);
3519  if (nb < 0) {
3520  break;
3521  }
3522  }
3523  break;
3524  default:
3525  break;
3526  }
3527  }
3528  return;
3529  } else if (fType == 31 || fType == 41) { // sub branch of a TClonesArray
3531  Int_t atype = fStreamerType;
3532  // FIXME: This should probably be > 59 instead.
3533  if (atype > 54) return;
3534  if (!fAddress) {
3535  return;
3536  }
3537  Int_t n = fNdata;
3538  if (atype>40) {
3539  atype -= 40;
3540  if (!fBranchCount2) return;
3541  const char *len_where = (char*)fBranchCount2->fAddress;
3542  if (!len_where) return;
3543  Int_t len_atype = fBranchCount2->fStreamerType;
3544  Int_t length;
3545  Int_t k;
3546  Char_t isArray;
3547  for( k=0; k<n; k++) {
3548  char **where = &(((char**)fAddress)[k]);
3549  delete [] *where;
3550  *where = 0;
3551  switch(len_atype) {
3552  case 1: {length = ((Char_t*) len_where)[k]; break;}
3553  case 2: {length = ((Short_t*) len_where)[k]; break;}
3554  case 3: {length = ((Int_t*) len_where)[k]; break;}
3555  case 4: {length = ((Long_t*) len_where)[k]; break;}
3556  //case 5: {length = ((Float_t*) len_where)[k]; break;}
3557  case 6: {length = ((Int_t*) len_where)[k]; break;}
3558  //case 8: {length = ((Double_t*)len_where)[k]; break;}
3559  case 11: {length = ((UChar_t*) len_where)[k]; break;}
3560  case 12: {length = ((UShort_t*) len_where)[k]; break;}
3561  case 13: {length = ((UInt_t*) len_where)[k]; break;}
3562  case 14: {length = ((ULong_t*) len_where)[k]; break;}
3563  case 15: {length = ((UInt_t*) len_where)[k]; break;}
3564  case 16: {length = ((Long64_t*) len_where)[k]; break;}
3565  case 17: {length = ((ULong64_t*)len_where)[k]; break;}
3566  case 18: {length = ((Bool_t*) len_where)[k]; break;}
3567  default: continue;
3568  }
3569  b >> isArray;
3570  if (length <= 0) continue;
3571  if (isArray == 0) continue;
3572  switch (atype) {
3573  case 1: {*where=new char[sizeof(Char_t)*length]; b.ReadFastArray((Char_t*) *where, length); break;}
3574  case 2: {*where=new char[sizeof(Short_t)*length]; b.ReadFastArray((Short_t*) *where, length); break;}
3575  case 3: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*) *where, length); break;}
3576  case 4: {*where=new char[sizeof(Long_t)*length]; b.ReadFastArray((Long_t*) *where, length); break;}
3577  case 5: {*where=new char[sizeof(Float_t)*length]; b.ReadFastArray((Float_t*) *where, length); break;}
3578  case 6: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*) *where, length); break;}
3579  case 8: {*where=new char[sizeof(Double_t)*length]; b.ReadFastArray((Double_t*)*where, length); break;}
3580  case 11: {*where=new char[sizeof(UChar_t)*length]; b.ReadFastArray((UChar_t*) *where, length); break;}
3581  case 12: {*where=new char[sizeof(UShort_t)*length]; b.ReadFastArray((UShort_t*)*where, length); break;}
3582  case 13: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*) *where, length); break;}
3583  case 14: {*where=new char[sizeof(ULong_t)*length]; b.ReadFastArray((ULong_t*) *where, length); break;}
3584  case 15: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*) *where, length); break;}
3585  case 16: {*where=new char[sizeof(Long64_t)*length]; b.ReadFastArray((Long64_t*) *where, length); break;}
3586  case 17: {*where=new char[sizeof(ULong64_t)*length]; b.ReadFastArray((ULong64_t*)*where, length); break;}
3587  case 18: {*where=new char[sizeof(Bool_t)*length]; b.ReadFastArray((Bool_t*) *where, length); break;}
3588  }
3589  }
3590  return;
3591  }
3592  if (atype > 20) {
3593  atype -= 20;
3595  n *= leaf->GetLenStatic();
3596  }
3597  switch (atype) {
3598  case 1: {b.ReadFastArray((Char_t*) fAddress, n); break;}
3599  case 2: {b.ReadFastArray((Short_t*) fAddress, n); break;}
3600  case 3: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3601  case 4: {b.ReadFastArray((Long_t*) fAddress, n); break;}
3602  case 5: {b.ReadFastArray((Float_t*) fAddress, n); break;}
3603  case 6: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3604  case 8: {b.ReadFastArray((Double_t*)fAddress, n); break;}
3605  case 11: {b.ReadFastArray((UChar_t*) fAddress, n); break;}
3606  case 12: {b.ReadFastArray((UShort_t*)fAddress, n); break;}
3607  case 13: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3608  case 14: {b.ReadFastArray((ULong_t*) fAddress, n); break;}
3609  case 15: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3610  case 16: {b.ReadFastArray((Long64_t*)fAddress, n); break;}
3611  case 17: {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
3612  case 18: {b.ReadFastArray((Bool_t*) fAddress, n); break;}
3613  case 9: {
3616  Double_t *xx = (Double_t*) fAddress;
3617  for (Int_t ii=0;ii<n;ii++) {
3618  b.ReadDouble32(&(xx[ii]),se);
3619  }
3620  break;
3621  }
3622  case 19: {
3625  Float_t *xx = (Float_t*) fAddress;
3626  for (Int_t ii=0;ii<n;ii++) {
3627  b.ReadFloat16(&(xx[ii]),se);
3628  }
3629  break;
3630  }
3631  }
3632  return;
3633  } else if (fType <= 2) { // branch in split mode
3634  // FIXME: This should probably be < 60 instead.
3635  if (fStreamerType > 40 && fStreamerType < 55) {
3636  Int_t atype = fStreamerType - 40;
3637  Int_t n;
3638  if (fBranchCount==0) {
3639  // Missing fBranchCount. let's attempts to recover.
3640 
3641  TString countname( GetName() );
3642  Ssiz_t dot = countname.Last('.');
3643  if (dot>=0) {
3644  countname.Remove(dot+1);
3645  } else {
3646  countname = "";
3647  }
3648  TString counter( GetTitle() );
3649  Ssiz_t loc = counter.Last('[');
3650  if (loc>=0) {
3651  counter.Remove(0,loc+1);
3652  }
3653  loc = counter.Last(']');
3654  if (loc>=0) {
3655  counter.Remove(loc);
3656  }
3657  countname += counter;
3658  SetBranchCount((TBranchElement *)fTree->GetBranch(countname));
3659  }
3660  if (fBranchCount) {
3661  n = (Int_t)fBranchCount->GetValue(0,0);
3662  } else {
3663  Warning("ReadLeaves","Missing fBranchCount for %s. Data will not be read correctly by the MakeClass mode.",GetName());
3664  n = 0;
3665  }
3666  fNdata = n;
3667  Char_t isArray;
3668  b >> isArray;
3669  switch (atype) {
3670  case 1: {b.ReadFastArray((Char_t*) fAddress, n); break;}
3671  case 2: {b.ReadFastArray((Short_t*) fAddress, n); break;}
3672  case 3: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3673  case 4: {b.ReadFastArray((Long_t*) fAddress, n); break;}
3674  case 5: {b.ReadFastArray((Float_t*) fAddress, n); break;}
3675  case 6: {b.ReadFastArray((Int_t*) fAddress, n); break;}
3676  case 8: {b.ReadFastArray((Double_t*)fAddress, n); break;}
3677  case 11: {b.ReadFastArray((UChar_t*) fAddress, n); break;}
3678  case 12: {b.ReadFastArray((UShort_t*)fAddress, n); break;}
3679  case 13: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3680  case 14: {b.ReadFastArray((ULong_t*) fAddress, n); break;}
3681  case 15: {b.ReadFastArray((UInt_t*) fAddress, n); break;}
3682  case 16: {b.ReadFastArray((Long64_t*) fAddress, n); break;}
3683  case 17: {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
3684  case 18: {b.ReadFastArray((Bool_t*) fAddress, n); break;}
3685  case 9: {
3688  Double_t *xx = (Double_t*) fAddress;
3689  for (Int_t ii=0;ii<n;ii++) {
3690  b.ReadDouble32(&(xx[ii]),se);
3691  }
3692  break;
3693  }
3694  case 19: {
3697  Float_t *xx = (Float_t*) fAddress;
3698  for (Int_t ii=0;ii<n;ii++) {
3699  b.ReadFloat16(&(xx[ii]),se);
3700  }
3701  break;
3702  }
3703  }
3704  } else {
3705  fNdata = 1;
3706  if (fAddress) {
3707  if (fType<0) {
3708  // Non TObject, Non collection classes with a custom streamer.
3709 
3710  // if (fObject)
3712  } else {
3713  TStreamerInfo *info = GetInfoImp();
3714  if (!info) {
3715  return;
3716  }
3717  // Since info is not null, fReadActionSequence is not null either.
3719  }
3721  fNdata = (Int_t) GetValue(0, 0);
3722  }
3723  } else {
3724  fNdata = 0;
3725  }
3726  }
3727  return;
3728  }
3729 }
3730 
3731 ////////////////////////////////////////////////////////////////////////////////
3732 /// Read leaves into i/o buffers for this branch.
3733 /// Case of a collection (fType == 4).
3734 
3736 {
3737  ValidateAddress();
3738  if (fObject == 0)
3739  {
3740  // We have nowhere to copy the data (probably because the data member was
3741  // 'dropped' from the current schema) so let's no copy it in a random place.
3742  return;
3743  }
3744 
3745  // STL container master branch (has only the number of elements).
3746  Int_t n;
3747  b >> n;
3748  if ((n < 0) || (n > fMaximum)) {
3749  if (IsMissingCollection()) {
3750  n = 0;
3751  b.SetBufferOffset(b.Length()-sizeof(n));
3752  } else {
3753  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());
3754  n = 0;
3755  }
3756  }
3757  fNdata = n;
3758 
3759  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,n);
3760 
3761  // Note: Proxy-helper needs to "embrace" the entire
3762  // streaming of this STL container if the container
3763  // is a set/multiset/map/multimap (what we do not
3764  // know here).
3765  // For vector/list/deque Allocate == Resize
3766  // and Commit == noop.
3767  // TODO: Exception safety a la TPushPop
3770  void* alternate = proxy->Allocate(fNdata, true);
3772  fPtrIterators->CreateIterators(alternate, proxy);
3773  } else {
3774  fIterators->CreateIterators(alternate, proxy);
3775  }
3776 
3777  Int_t nbranches = fBranches.GetEntriesFast();
3778  switch (fSTLtype) {
3779  case ROOT::kSTLset:
3782  case ROOT::kSTLmultiset:
3783  case ROOT::kSTLmap:
3784  case ROOT::kSTLmultimap:
3787  for (Int_t i = 0; i < nbranches; ++i) {
3788  TBranch *branch = (TBranch*) fBranches[i];
3789  Int_t nb = branch->GetEntry(GetReadEntry(), 1);
3790  if (nb < 0) {
3791  // Give up on i/o failure.
3792  // FIXME: We need an error message here.
3793  break;
3794  }
3795  }
3796  break;
3797  default:
3798  break;
3799  }
3800  //------------------------------------------------------------------------
3801  // We have split this stuff, so we need to create the the pointers
3802  /////////////////////////////////////////////////////////////////////////////
3803 
3805  {
3806  TClass *elClass = proxy->GetValueClass();
3807 
3808  //--------------------------------------------------------------------
3809  // The allocation is done in this strange way because ReadLeaves
3810  // is being called many times by TTreeFormula!!!
3811  //////////////////////////////////////////////////////////////////////////
3812 
3813  Int_t i = 0;
3814  // coverity[returned_null] the fNdata is check enough to prevent the use of null value of At(0)
3815  if( !fNdata || *(void**)proxy->At( 0 ) != 0 )
3816  i = fNdata;
3817 
3818  for( ; i < fNdata; ++i )
3819  {
3820  void **el = (void**)proxy->At( i );
3821  // coverity[dereference] since this is a member streaming action by definition the collection contains objects and elClass is not null.
3822  *el = elClass->New();
3823  }
3824  }
3825 
3826  proxy->Commit(alternate);
3827 }
3828 
3829 ////////////////////////////////////////////////////////////////////////////////
3830 /// Read leaves into i/o buffers for this branch.
3831 /// Case of a data member within a collection (fType == 41).
3832 
3834 {
3835  ValidateAddress();
3836  if (fObject == 0)
3837  {
3838  // We have nowhere to copy the data (probably because the data member was
3839  // 'dropped' from the current schema) so let's no copy it in a random place.
3840  return;
3841  }
3842 
3843  // STL container sub-branch (contains the elements).
3845  if (!fNdata) {
3846  return;
3847  }
3848 
3849  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3850 
3851  TStreamerInfo *info = GetInfoImp();
3852  if (info == 0) return;
3853 
3856 
3857  // R__ASSERT(0);
3859  b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
3860 
3861  // char **arr = (char **)proxy->At(0);
3862  // char **end = arr + proxy->Size();
3863  // fReadActionSequence->ReadBufferVecPtr(b,arr,end);
3864 
3865  // info->ReadBufferSTLPtrs(b, proxy, fNdata, fID, fOffset);
3866  // for(UInt_t ii=0; ii < fIDs.size(); ++ii) {
3867  // info->ReadBufferSTLPtrs(b, proxy, fNdata, fIDs[ii], fOffset);
3868  // }
3869 }
3870 
3871 ////////////////////////////////////////////////////////////////////////////////
3872 /// Read leaves into i/o buffers for this branch.
3873 /// Case of a data member within a collection (fType == 41).
3874 
3876 {
3877  ValidateAddress();
3878  if (fObject == 0)
3879  {
3880  // We have nowhere to copy the data (probably because the data member was
3881  // 'dropped' from the current schema) so let's no copy it in a random place.
3882  return;
3883  }
3884 
3885  // STL container sub-branch (contains the elements).
3887  if (!fNdata) {
3888  return;
3889  }
3890  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3891 
3892  TStreamerInfo *info = GetInfoImp();
3893  if (info == 0) return;
3894 
3897 
3900 }
3901 
3902 ////////////////////////////////////////////////////////////////////////////////
3903 /// Read leaves into i/o buffers for this branch.
3904 /// Case of a data member within a collection (fType == 41).
3905 
3907 {
3908  ValidateAddress();
3909  if (fObject == 0)
3910  {
3911  // We have nowhere to copy the data (probably because the data member was
3912  // 'dropped' from the current schema) so let's no copy it in a random place.
3913  return;
3914  }
3915 
3916  // STL container sub-branch (contains the elements).
3918  if (!fNdata) {
3919  return;
3920  }
3921  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
3922 
3923  TStreamerInfo *info = GetInfoImp();
3924  if (info == 0) return;
3925  // Since info is not null, fReadActionSequence is not null either.
3926 
3927  // Still calling PushPop for the legacy entries.
3930 
3932  b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
3933 }
3934 
3935 ////////////////////////////////////////////////////////////////////////////////
3936 /// Read leaves into i/o buffers for this branch.
3937 /// Case of a TClonesArray (fType == 3).
3938 
3940 {
3941  ValidateAddress();
3942  if (fObject == 0)
3943  {
3944  // We have nowhere to copy the data (probably because the data member was
3945  // 'dropped' from the current schema) so let's no copy it in a random place.
3946  return;
3947  }
3948 
3949  // TClonesArray master branch (has only the number of elements).
3950  Int_t n;
3951  b >> n;
3952  if ((n < 0) || (n > fMaximum)) {
3953  if (IsMissingCollection()) {
3954  n = 0;
3955  b.SetBufferOffset(b.Length()-sizeof(n));
3956  } else {
3957  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());
3958  n = 0;
3959  }
3960  }
3961  fNdata = n;
3962  TClonesArray* clones = (TClonesArray*) fObject;
3963  if (clones->IsZombie()) {
3964  return;
3965  }
3966  // The salient part of Clear is now 'duplicated in ExpandCreateFast (i.e. the
3967  // setting to zero of the unused slots), so we no longer need to call Clear explicitly
3968  // clones->Clear();
3969  clones->ExpandCreateFast(fNdata);
3970 }
3971 
3972 ////////////////////////////////////////////////////////////////////////////////
3973 /// Read leaves into i/o buffers for this branch.
3974 /// Case of a data member within a TClonesArray (fType == 31).
3975 
3977 {
3978  // No need to validate the address here, if we are a member of a split ClonesArray,
3979  // fID is positive
3980  // ValidateAddress();
3981 
3982  if (fObject == 0)
3983  {
3984  // We have nowhere to copy the data (probably because the data member was
3985  // 'dropped' from the current schema) so let's no copy it in a random place.
3986  return;
3987  }
3988 
3989  // TClonesArray sub-branch (contains the elements).
3991  TClonesArray* clones = (TClonesArray*) fObject;
3992  if (clones->IsZombie()) {
3993  return;
3994  }
3995  TStreamerInfo *info = GetInfoImp();
3996  if (info==0) return;
3997  // Since info is not null, fReadActionSequence is not null either.
3998 
3999  // Note, we could (possibly) save some more, by configuring the action
4000  // based on the value of fOnfileObject rather than pushing in on a stack.
4001  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,fNdata);
4002 
4003  char **arr = (char **)clones->GetObjectRef();
4004  char **end = arr + fNdata;
4006 }
4007 
4008 ////////////////////////////////////////////////////////////////////////////////
4009 /// Read leaves into i/o buffers for this branch.
4010 /// For split-class branch, base class branch, data member branch, or top-level branch.
4011 /// which do not have a branch count and are not a counter.
4012 
4014 {
4015  R__ASSERT(fBranchCount==0);
4017 
4018  ValidateAddress();
4019  if (fObject == 0)
4020  {
4021  // We have nowhere to copy the data (probably because the data member was
4022  // 'dropped' from the current schema) so let's no copy it in a random place.
4023  return;
4024  }
4025 
4026  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4027  // If not a TClonesArray or STL container master branch
4028  // or sub-branch and branch inherits from tobject,
4029  // then register with the buffer so that pointers are
4030  // handled properly.
4031  if (TestBit(kBranchObject)) {
4032  b.MapObject((TObject*) fObject);
4033  } else if (TestBit(kBranchAny)) {
4035  }
4036 
4037  fNdata = 1;
4038  TStreamerInfo *info = GetInfoImp();
4039  if (!info) {
4040  return;
4041  }
4042  // Since info is not null, fReadActionSequence is not null either.
4044 }
4045 
4046 ////////////////////////////////////////////////////////////////////////////////
4047 /// Read leaves into i/o buffers for this branch.
4048 /// For split-class branch, base class branch, data member branch, or top-level branch.
4049 /// which do have a branch count and are not a counter.
4050 
4052 {
4054 
4055  ValidateAddress();
4056  if (fObject == 0)
4057  {
4058  // We have nowhere to copy the data (probably because the data member was
4059  // 'dropped' from the current schema) so let's no copy it in a random place.
4060  return;
4061  }
4062 
4063  // If not a TClonesArray or STL container master branch
4064  // or sub-branch and branch inherits from tobject,
4065  // then register with the buffer so that pointers are
4066  // handled properly.
4067  if (TestBit(kBranchObject)) {
4068  b.MapObject((TObject*) fObject);
4069  } else if (TestBit(kBranchAny)) {
4071  }
4072 
4073  fNdata = (Int_t) fBranchCount->GetValue(0, 0);
4074  TStreamerInfo *info = GetInfoImp();
4075  if (!info) {
4076  return;
4077  }
4078  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1); // Here we have a single object that contains a variable size C-style array.
4079  // Since info is not null, fReadActionSequence is not null either.
4081 }
4082 
4083 ////////////////////////////////////////////////////////////////////////////////
4084 /// Read leaves into i/o buffers for this branch.
4085 /// For split-class branch, base class branch, data member branch, or top-level branch.
4086 /// which do not have a branch count and are a counter.
4087 
4089 {
4090  ValidateAddress();
4091  if (fObject == 0)
4092  {
4093  // We have nowhere to copy the data (probably because the data member was
4094  // 'dropped' from the current schema) so let's no copy it in a random place.
4095  return;
4096  }
4097 
4098  // If not a TClonesArray or STL container master branch
4099  // or sub-branch and branch inherits from tobject,
4100  // then register with the buffer so that pointers are
4101  // handled properly.
4102  if (TestBit(kBranchObject)) {
4103  b.MapObject((TObject*) fObject);
4104  } else if (TestBit(kBranchAny)) {
4106  }
4107 
4108  TStreamerInfo *info = GetInfoImp();
4109  if (!info) {
4110  return;
4111  }
4112 
4113  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4114 
4115  // Since info is not null, fReadActionSequence is not null either.
4117  fNdata = (Int_t) GetValue(0, 0);
4118 }
4119 
4120 ////////////////////////////////////////////////////////////////////////////////
4121 /// Read leaves into i/o buffers for this branch.
4122 /// Non TObject, Non collection classes with a custom streamer.
4123 
4125 {
4126  ValidateAddress();
4127  if (fObject == 0)
4128  {
4129  // We have nowhere to copy the data (probably because the data member was
4130  // 'dropped' from the current schema) so let's no copy it in a random place.
4131  return;
4132  }
4133 
4134  R__PushCache onfileObject(((TBufferFile&)b),fOnfileObject,1);
4136 }
4137 
4138 ////////////////////////////////////////////////////////////////////////////////
4139 /// Unconfiguration Fill Leave function.
4140 
4142 {
4143  Fatal("FillLeaves","The FillLeaves function has not been configured for %s",GetName());
4144 }
4145 
4146 ////////////////////////////////////////////////////////////////////////////////
4147 /// Delete any object we may have allocated on a previous call to SetAddress.
4148 
4150 {
4151  if (fObject && TestBit(kDeleteObject)) {
4152  if (IsAutoDelete() && fAddress != (char*)&fObject) {
4153  *((char**) fAddress) = 0;
4154  }
4156  if (fType == 3) {
4157  // -- We are a TClonesArray master branch.
4158  TClonesArray::Class()->Destructor(fObject);
4159  fObject = 0;
4162  // -- We are a pointer to a TClonesArray.
4163  // We must zero the pointer in the object.
4164  *((char**) fAddress) = 0;
4165  }
4166  } else if (fType == 4) {
4167  // -- We are an STL container master branch.
4169 
4170  if (!proxy) {
4171  Warning("ReleaseObject", "Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
4172  fObject = 0;
4173  } else {
4175  if (needDelete && fID >= 0) {
4178  needDelete = !se->TestBit(TStreamerElement::kDoNotDelete);
4179  }
4180  if (needDelete) {
4181  TVirtualCollectionProxy::TPushPop helper(proxy,fObject);
4182  proxy->Clear("force");
4183  }
4184  proxy->Destructor(fObject);
4185  fObject = 0;
4186  }
4188  // -- We are a pointer to an STL container.
4189  // We must zero the pointer in the object.
4190  *((char**) fAddress) = 0;
4191  }
4192  } else {
4193  // We are *not* a TClonesArray master branch and we are *not* an STL container master branch.
4194  TClass* cl = fBranchClass.GetClass();
4195  if (!cl) {
4196  Warning("ReleaseObject", "Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
4197  fObject = 0;
4198  } else {
4200 
4201  if (proxy) {
4202  if (fID >= 0) {
4204  TStreamerElement* se = si->GetElement(fID);
4206  TVirtualCollectionProxy::TPushPop helper(proxy,fObject);
4207  proxy->Clear("force");
4208  }
4210  TVirtualCollectionProxy::TPushPop helper(proxy,fObject);
4211  proxy->Clear("force");
4212  }
4213 
4214  }
4215  cl->Destructor(fObject);
4216  fObject = 0;
4217  }
4218  }
4219  }
4220 }
4221 
4222 ////////////////////////////////////////////////////////////////////////////////
4223 /// Reset a Branch.
4224 ///
4225 /// Existing i/o buffers are deleted.
4226 /// Entries, max and min are reset.
4227 ///
4228 
4230 {
4231  Int_t nbranches = fBranches.GetEntriesFast();
4232  for (Int_t i = 0; i < nbranches; ++i) {
4233  TBranch* branch = (TBranch*) fBranches[i];
4234  branch->Reset(option);
4235  }
4236  fBranchID = -1;
4237  TBranch::Reset(option);
4238 }
4239 
4240 ////////////////////////////////////////////////////////////////////////////////
4241 /// Reset a Branch after a Merge operation (drop data but keep customizations)
4242 ///
4243 
4245 {
4246  Int_t nbranches = fBranches.GetEntriesFast();
4247  for (Int_t i = 0; i < nbranches; ++i) {
4248  TBranch* branch = (TBranch*) fBranches[i];
4249  branch->ResetAfterMerge(info);
4250  }
4252 }
4253 
4254 ////////////////////////////////////////////////////////////////////////////////
4255 /// Set branch address to zero and free all allocated memory.
4256 
4258 {
4259  for (Int_t i = 0; i < fNleaves; ++i) {
4260  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4261  //if (leaf) leaf->SetAddress(0);
4262  leaf->SetAddress(0);
4263  }
4264 
4265  // Note: We *must* do the sub-branches first, otherwise
4266  // we may delete the object containing the sub-branches
4267  // before giving them a chance to cleanup.
4268  Int_t nbranches = fBranches.GetEntriesFast();
4269  for (Int_t i = 0; i < nbranches; ++i) {
4270  TBranch* br = (TBranch*) fBranches[i];
4271  if (br) br->ResetAddress();
4272  }
4273 
4274  //
4275  // SetAddress may have allocated an object.
4276  //
4277 
4278  ReleaseObject();
4279 
4281  fAddress = 0;
4282  fObject = 0;
4283 }
4284 
4285 ////////////////////////////////////////////////////////////////////////////////
4286 /// Release ownership of any allocated objects.
4287 ///
4288 /// Note: This interface was added so that clone trees could
4289 /// be told they do not own the allocated objects.
4290 
4292 {
4295  for (Int_t i = 0; i < nb; ++i) {
4296  TBranch* br = (TBranch*) fBranches[i];
4297  if (br->InheritsFrom(TBranchElement::Class())) {
4298  ((TBranchElement*) br)->ResetDeleteObject();
4299  }
4300  }
4301 }
4302 
4303 ////////////////////////////////////////////////////////////////////////////////
4304 /// Point this branch at an object.
4305 ///
4306 /// For a sub-branch, addr is a pointer to the branch object.
4307 ///
4308 /// For a top-level branch the meaning of addr is as follows:
4309 ///
4310 /// If addr is zero, then we allocate a branch object
4311 /// internally and the branch is the owner of the allocated
4312 /// object, not the caller. However the caller may obtain
4313 /// a pointer to the branch object with GetObject().
4314 ///
4315 /// Example:
4316 /// ~~~ {.cpp}
4317 /// branch->SetAddress(0);
4318 /// Event* event = branch->GetObject();
4319 /// ... Do some work.
4320 /// ~~~
4321 /// If addr is not zero, but the pointer addr points at is
4322 /// zero, then we allocate a branch object and set the passed
4323 /// pointer to point at the allocated object. The caller
4324 /// owns the allocated object and is responsible for deleting
4325 /// it when it is no longer needed.
4326 ///
4327 /// Example:
4328 /// ~~~ {.cpp}
4329 /// Event* event = 0;
4330 /// branch->SetAddress(&event);
4331 /// ... Do some work.
4332 /// delete event;
4333 /// event = 0;
4334 /// ~~~
4335 /// If addr is not zero and the pointer addr points at is
4336 /// also not zero, then the caller has allocated a branch
4337 /// object and is asking us to use it. The caller owns it
4338 /// and must delete it when it is no longer needed.
4339 ///
4340 /// Example:
4341 /// ~~~ {.cpp}
4342 /// Event* event = new Event();
4343 /// branch->SetAddress(&event);
4344 /// ... Do some work.
4345 /// delete event;
4346 /// event = 0;
4347 /// ~~~
4348 /// These rules affect users of TTree::Branch(),
4349 /// TTree::SetBranchAddress(), and TChain::SetBranchAddress()
4350 /// as well because those routines call this one.
4351 ///
4352 /// An example of a tree with branches with objects allocated
4353 /// and owned by us:
4354 /// ~~~ {.cpp}
4355 /// TFile* f1 = new TFile("myfile_original.root");
4356 /// TTree* t1 = (TTree*) f->Get("MyTree");
4357 /// TFile* f2 = new TFile("myfile_copy.root", "recreate");
4358 /// TTree* t2 = t1->Clone(0);
4359 /// for (Int_t i = 0; i < 10; ++i) {
4360 /// t1->GetEntry(i);
4361 /// t2->Fill();
4362 /// }
4363 /// t2->Write()
4364 /// delete f2;
4365 /// f2 = 0;
4366 /// delete f1;
4367 /// f1 = 0;
4368 /// ~~~
4369 /// An example of a branch with an object allocated by us,
4370 /// but owned by the caller:
4371 /// ~~~ {.cpp}
4372 /// TFile* f = new TFile("myfile.root", "recreate");
4373 /// TTree* t = new TTree("t", "A test tree.")
4374 /// Event* event = 0;
4375 /// TBranchElement* br = t->Branch("event.", &event);
4376 /// for (Int_t i = 0; i < 10; ++i) {
4377 /// ... Fill event with meaningful data in some way.
4378 /// t->Fill();
4379 /// }
4380 /// t->Write();
4381 /// delete event;
4382 /// event = 0;
4383 /// delete f;
4384 /// f = 0;
4385 /// ~~~
4386 /// Notice that the only difference between this example
4387 /// and the following example is that the event pointer
4388 /// is zero when the branch is created.
4389 ///
4390 /// An example of a branch with an object allocated and
4391 /// owned by the caller:
4392 /// ~~~ {.cpp}
4393 /// TFile* f = new TFile("myfile.root", "recreate");
4394 /// TTree* t = new TTree("t", "A test tree.")
4395 /// Event* event = new Event();
4396 /// TBranchElement* br = t->Branch("event.", &event);
4397 /// for (Int_t i = 0; i < 10; ++i) {
4398 /// ... Fill event with meaningful data in some way.
4399 /// t->Fill();
4400 /// }
4401 /// t->Write();
4402 /// delete event;
4403 /// event = 0;
4404 /// delete f;
4405 /// f = 0;
4406 /// ~~~
4407 /// If AutoDelete is on (see TBranch::SetAutoDelete),
4408 /// the top level objet will be deleted and recreate
4409 /// each time an entry is read, whether or not the
4410 /// TTree owns the object.
4411 
4413 {
4414  //
4415  // Don't bother if we are disabled.
4416  //
4417 
4418  if (TestBit(kDoNotProcess)) {
4419  return;
4420  }
4421 
4422  //
4423  // FIXME: When would this happen?
4424  //
4425 
4426  if (fType < -1) {
4427  return;
4428  }
4429 
4431 
4432  //
4433  // Special case when called from code generated by TTree::MakeClass.
4434  //
4435 
4436  if (Long_t(addr) == -1) {
4437  // FIXME: Do we have to release an object here?
4438  // ReleaseObject();
4439  fAddress = (char*) -1;
4440  fObject = (char*) -1;
4442  return;
4443  }
4444 
4445  //
4446  // Reset last read entry number, we have a new user object now.
4447  //
4448 
4449  fReadEntry = -1;
4450 
4451  //
4452  // Make sure our branch class is instantiated.
4453  //
4454  TClass* clOfBranch = fBranchClass.GetClass();
4455  if( fTargetClass.GetClassName()[0] ) {
4456  clOfBranch = fTargetClass;
4457  }
4458 
4459  //
4460  // Try to build the streamer info.
4461  //
4462 
4463  TStreamerInfo *info = GetInfoImp();
4464 
4465  // FIXME: Warn about failure to get the streamer info here?
4466 
4467  //
4468  // We may have allocated an object last time we were called.
4469  //
4470 
4471  if (fObject && TestBit(kDeleteObject)){
4472  ReleaseObject();
4473  }
4474 
4475  //
4476  // Remember the pointer to the pointer to our object.
4477  //
4478 
4479  fAddress = (char*) addr;
4480  if (fAddress != (char*)(&fObject)) {
4481  fObject = 0;
4482  }
4484 
4485  //
4486  // Do special stuff if we got called from a MakeClass class.
4487  // Allow sub-branches to have independently set addresses.
4488  //
4489 
4490  if (fTree->GetMakeClass()) {
4491  if (fID > -1) {
4492  // We are *not* a top-level branch.
4493  if (!info) {
4494  // No streamer info, give up.
4495  // FIXME: We should have an error message here.
4496  fObject = fAddress;
4497  } else {
4498  // Compensate for the fact that the i/o routines
4499  // will add the streamer offset to the address.
4500  fObject = fAddress - info->TStreamerInfo::GetElementOffset(fID);
4501  }
4502  return;
4503  }
4504  }
4505 
4506  //
4507  // Check whether the container type is still the same
4508  // to support schema evolution; what is written on the file
4509  // may no longer match the class code which is loaded.
4510  //
4511 
4512  if (fType == 3) {
4513  // split TClonesArray, counter/master branch.
4514  TClass* clm = fClonesClass;
4515  if (clm) {
4516  // In case clm derives from an abstract class.
4517  clm->BuildRealData();
4518  clm->GetStreamerInfo();
4519  }
4520  TClass* newType = GetCurrentClass();
4521  if (newType && (newType != TClonesArray::Class())) {
4522  // The data type of the container has changed.
4523  //
4524  // Let's check if it is a compatible type:
4525  Bool_t matched = kFALSE;
4526  if (newType->GetCollectionProxy()) {
4527  TClass *content = newType->GetCollectionProxy()->GetValueClass();
4528  if (clm == content) {
4529  matched = kTRUE;
4530  } else {
4531  Warning("SetAddress", "The type of %s was changed from TClonesArray to %s but the content do not match (was %s)!", GetName(), newType->GetName(), GetClonesName());
4532  }
4533  } else {
4534  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());
4535  }
4536  if (matched) {
4537  // Change from 3/31 to 4/41
4538  SetType(4);
4539  // Set the proxy.
4540  fSTLtype = newType->GetCollectionType();
4541  fCollProxy = newType->GetCollectionProxy()->Generate();
4542 
4544  SetReadLeavesPtr();
4545  SetFillLeavesPtr();
4546 
4552  } else {
4554  }
4555  } else {
4556  // FIXME: Must maintain fObject here as well.
4557  fAddress = 0;
4558  }
4559  }
4560  } else if (fType == 4) {
4561  // split STL container, counter/master branch.
4562  TClass* newType = GetCurrentClass();
4563  if (newType && (newType != GetCollectionProxy()->GetCollectionClass())) {
4564  // Let's check if it is a compatible type:
4565  TVirtualCollectionProxy* newProxy = newType->GetCollectionProxy();
4567  if (newProxy && (oldProxy->GetValueClass() == newProxy->GetValueClass()) && ((!oldProxy->GetValueClass() && (oldProxy->GetType() == newProxy->GetType())) || (oldProxy->GetValueClass() && (oldProxy->HasPointers() == newProxy->HasPointers())))) {
4568  delete fCollProxy;
4569  Int_t nbranches = GetListOfBranches()->GetEntries();
4570  fCollProxy = newType->GetCollectionProxy()->Generate();
4572  for (Int_t i = 0; i < nbranches; ++i) {
4574  br->fCollProxy = 0;
4575  if (br->fReadActionSequence) {
4576  br->SetReadActionSequence();
4577  }
4578  if (br->fFillActionSequence) {
4579  br->SetFillActionSequence();
4580  }
4581  }
4584  SetReadLeavesPtr();
4585  SetFillLeavesPtr();
4586  delete fIterators;
4587  delete fPtrIterators;
4593  } else {
4595  }
4596  }
4597  else if (newProxy && (oldProxy->HasPointers() == newProxy->HasPointers()) && (oldProxy->GetValueClass()!=0) && (newProxy->GetValueClass()!=0)) {
4598  // Let see if there is a rule to convert the content of the collection into each other.
4599  if (newType->GetSchemaRules()->HasRuleWithSourceClass( oldProxy->GetCollectionClass()->GetName())) {
4600  TClass *oldValueClass = oldProxy->GetValueClass();
4601  delete fCollProxy;
4602  Int_t nbranches = GetListOfBranches()->GetEntries();
4603  fCollProxy = newType->GetCollectionProxy()->Generate();
4605  for (Int_t i = 0; i < nbranches; ++i) {
4607  br->fCollProxy = 0;
4608  if (br->fBranchClass == oldValueClass) {
4610  }
4611  if (br->fReadActionSequence) {
4612  br->SetReadActionSequence();
4613  }
4614  if (br->fFillActionSequence) {
4615  br->SetFillActionSequence();
4616  }
4617  }
4620  SetReadLeavesPtr();
4621  SetFillLeavesPtr();
4622  delete fIterators;
4623  delete fPtrIterators;
4629  } else {
4631  }
4632  } else {
4633  Error("SetAddress","For %s, we can not convert %s into %s\n",
4634  GetName(),oldProxy->GetCollectionClass()->GetName(),newType->GetName());
4635  fAddress = 0;
4636  fObject = 0;
4637  return;
4638  }
4639  }
4640  else if ((newType == TClonesArray::Class()) && (oldProxy->GetValueClass() && !oldProxy->HasPointers() && oldProxy->GetValueClass()->IsTObject()))
4641  {
4642  // The new collection and the old collection are not compatible,
4643  // we cannot use the new collection to read the data.
4644  // Actually we could check if the new collection is a
4645  // compatible ROOT collection.
4646 
4647  // We cannot insure that the TClonesArray is set for the
4648  // proper class (oldProxy->GetValueClass()), so we assume that
4649  // the transformation was done properly by the class designer.
4650 
4651  // Change from 4/41 to 3/31
4652  SetType(3);
4653  // Reset the proxy.
4654  fSTLtype = kNone;
4655  switch(fStreamerType) {
4659  break;
4663  break;
4666  break;
4667  }
4668  fClonesClass = oldProxy->GetValueClass();
4670  delete fCollProxy;
4671  fCollProxy = 0;
4672  TClass* clm = fClonesClass;
4673  if (clm) {
4674  clm->BuildRealData(); //just in case clm derives from an abstract class
4675  clm->GetStreamerInfo();
4676  }
4678  SetReadLeavesPtr();
4679  SetFillLeavesPtr();
4680  delete fIterators;
4681  fIterators = 0;
4682  delete fPtrIterators;
4683  fPtrIterators =0;
4684  } else {
4685  // FIXME: We must maintain fObject here as well.
4686  Error("SetAddress","For %s can not convert %s into %s\n",GetName(),GetCurrentClass()->GetName(),newType->GetName());
4687  fAddress = 0;
4688  return;
4689  }
4690  } else {
4691  if (!fIterators && !fPtrIterators) {
4697  } else {
4699  }
4700  }
4701  }
4702  }
4703 
4704  //
4705  // Establish the semantics of fObject and fAddress.
4706  //
4707  // Top-level branch:
4708  // fObject is a ptr to the object,
4709  // fAddress is a ptr to a pointer to the object.
4710  //
4711  // Sub-branch:
4712  // fObject is a ptr to the object,
4713  // fAddress is the same as fObject.
4714  //
4715  //
4716  // There are special cases for TClonesArray and STL containers.
4717  // If there is no user-provided object, we allocate one. We must
4718  // also initialize any STL container proxy.
4719  //
4720 
4721  if (fType == 3) {
4722  // -- We are a TClonesArray master branch.
4723  if (fAddress) {
4724  // -- We have been given a non-zero address, allocate if necessary.
4726  // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
4727  // Case of an embedded TClonesArray.
4728  fObject = fAddress;
4729  // Check if it has already been properly built.
4730  TClonesArray* clones = (TClonesArray*) fObject;
4731  if (!clones->GetClass()) {
4733  }
4734  } else {
4735  // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
4736  // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
4737  if ((fStreamerType != -1) &&
4740  Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
4741  } else if (fStreamerType == -1) {
4742  // -- We are a top-level branch.
4743  TClonesArray** pp = (TClonesArray**) fAddress;
4744  if (!*pp) {
4745  // -- Caller wants us to allocate the clones array, but they will own it.
4746  *pp = new TClonesArray(fClonesClass);
4747  }
4748  fObject = (char*) *pp;
4749  } else {
4750  // -- We are a pointer to a TClonesArray.
4751  // Note: We do this so that the default constructor,
4752  // or the i/o constructor can be lazy.
4753  TClonesArray** pp = (TClonesArray**) fAddress;
4754  if (!*pp) {
4755  // -- Caller wants us to allocate the clones array, but they will own it.
4756  *pp = new TClonesArray(fClonesClass);
4757  }
4758  fObject = (char*) *pp;
4759  }
4760  }
4761  } else {
4762  // -- We have been given a zero address, allocate for top-level only.
4764  // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
4765  // Case of an embedded TClonesArray.
4766  Error("SetAddress", "Embedded TClonesArray given a zero address for branch '%s'", GetName());
4767  } else {
4768  // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
4769  // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
4770  if ((fStreamerType != -1) &&
4773  Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
4774  } else if (fStreamerType == -1) {
4775  // -- We are a top-level branch.
4776  // Idea: Consider making a zero address not allocate.
4778  fObject = (char*) new TClonesArray(fClonesClass);
4779  fAddress = (char*) &fObject;
4780  } else {
4781  // -- We are a sub-branch which is a pointer to a TClonesArray.
4782  Error("SetAddress", "Embedded pointer to a TClonesArray given a zero address for branch '%s'", GetName());
4783  }
4784  }
4785  }
4786  } else if (fType == 4) {
4787  // -- We are an STL container master branch.
4788  //
4789  // Initialize fCollProxy.
4791  if (fAddress) {
4792  // -- We have been given a non-zero address, allocate if necessary.
4796  // We are *not* a top-level branch and we are *not* a pointer to an STL container.
4797  // Case of an embedded STL container.
4798  // Note: We test for the kObject and kAny types to support
4799  // the (unwise) choice of inheriting from an STL container.
4800  fObject = fAddress;
4801  } else {
4802  // We are either a top-level branch or subbranch which is a pointer to an STL container.
4803  // Streamer type should be -1 (for a top-level branch) or kSTLp here.
4805  Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
4806  } else if (fStreamerType == -1) {
4807  // -- We are a top-level branch.
4808  void** pp = (void**) fAddress;
4809  if (!*pp) {
4810  // -- Caller wants us to allocate the STL container, but they will own it.
4811  *pp = proxy->New();
4812  if (!(*pp)) {
4813  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4814  // FIXME: Should we do this? Lots of other code wants
4815  // fAddress to be zero if no fObject, but is
4816  // that a good thing?
4817  fAddress = 0;
4818  }
4819  }
4820  fObject = (char*) *pp;
4821  } else {
4822  // -- We are a pointer to an STL container.
4823  // Note: We do this so that the default constructor,
4824  // or the i/o constructor can be lazy.
4825  void** pp = (void**) fAddress;
4826  if (!*pp) {
4827  // -- Caller wants us to allocate the STL container, but they will own it.
4828  *pp = proxy->New();
4829  if (!(*pp)) {
4830  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4831  // FIXME: Should we do this? Lots of other code wants
4832  // fAddress to be zero if no fObject, but is
4833  // that a good thing?
4834  fAddress = 0;
4835  }
4836  }
4837  fObject = (char*) *pp;
4838  }
4839  }
4840  } else {
4841  // -- We have been given a zero address, allocate for top-level only.
4845  // We are *not* a top-level branch and we are *not* a pointer to an STL container.
4846  // Case of an embedded STL container.
4847  // Note: We test for the kObject and kAny types to support
4848  // the (unwise) choice of inheriting from an STL container.
4849  Error("SetAddress", "Embedded STL container given a zero address for branch '%s'", GetName());
4850  } else {
4851  // We are either a top-level branch or sub-branch which is a pointer to an STL container.
4852  // Streamer type should be -1 (for a top-level branch) or kSTLp here.
4854  Error("SetAddress", "STL container with fStreamerType: %d", fStreamerType);
4855  } else if (fStreamerType == -1) {
4856  // -- We are a top-level branch, allocate.
4858  fObject = (char*) proxy->New();
4859  if (fObject) {
4860  fAddress = (char*) &fObject;
4861  } else {
4862  Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
4863  // FIXME: Should we do this? Lots of other code wants
4864  // fAddress to be zero if no fObject, but is
4865  // that a good thing?
4866  fAddress = 0;
4867  }
4868  } else {
4869  // -- We are a sub-branch which is a pointer to an STL container.
4870  Error("SetAddress", "Embedded pointer to an STL container given a zero address for branch '%s'", GetName());
4871  }
4872  }
4873  }
4874  } else if (fType == 41) {
4875  // -- We are an STL container sub-branch.
4876  // Initialize fCollProxy.
4878  // We are not at top-level branch.
4879  fObject = fAddress;
4880  } else if (fID < 0) {
4881  // -- We are a top-level branch.
4882  char** pp = (char**) fAddress;
4883  if (pp && *pp) {
4884  // -- Caller provided an i/o buffer for us to use.
4885  fObject = *pp;
4886  } else {
4887  // -- Caller did not provide an i/o buffer for us to use, we must make one for ourselves.
4888  if (clOfBranch) {
4889  if (!pp) {
4890  // -- Caller wants us to own the object.
4892  }
4893  fObject = (char*) clOfBranch->New();
4894  if (pp) {
4895  *pp = fObject;
4896  } else {
4897  fAddress = (char*) &fObject;
4898  }
4899  } else {
4900  Error("SetAddress", "I have no TClass for branch %s, so I cannot allocate an I/O buffer!", GetName());
4901  if (pp) {
4902  fObject = 0;
4903  *pp = 0;
4904  }
4905  }
4906  }
4907  } else {
4908  // -- We are *not* a top-level branch.
4909  fObject = fAddress;
4910  }
4911 
4912  if (!info) {
4913  // FIXME: We need and error message here, no streamer info, so cannot set offsets.
4914  return;
4915  }
4916 
4917  // We do this only once because it depends only on
4918  // the type of our object, not on its address.
4919  if (!fInitOffsets) {
4921  }
4922 
4923  // We are split, recurse down to our sub-branches.
4924  //
4925  // FIXME: This is a tail recursion, we burn stack.
4926  Int_t nbranches = fBranches.GetEntriesFast();
4927  for (Int_t i = 0; i < nbranches; ++i) {
4928  TBranch* abranch = (TBranch*) fBranches.UncheckedAt(i);
4929  // FIXME: This is a tail recursion!
4931  abranch->SetAddress(fObject + fBranchOffset[i]);
4932  abranch->SetBit(kAddressSet);
4933  } else {
4934  // When the member is missing, just leave the address alone
4935  // (since setting explicitly to 0 would trigger error/warning
4936  // messages).
4937  // abranch->SetAddress(0);
4938  abranch->SetBit(kAddressSet);
4939  }
4940  }
4941 }
4942 
4943 ////////////////////////////////////////////////////////////////////////////////
4944 /// Reset the basket size for all sub-branches of this branch element.
4945 
4947 {
4948  TBranch::SetBasketSize(buffsize);
4949  Int_t nbranches = fBranches.GetEntriesFast();
4950  for (Int_t i = 0; i < nbranches; ++i) {
4951  TBranch* branch = (TBranch*) fBranches[i];
4952  branch->SetBasketSize(fBasketSize);
4953  }
4954 }
4955 
4956 ////////////////////////////////////////////////////////////////////////////////
4957 /// Set the branch counter for this branch.
4958 
4960 {
4961  fBranchCount = brOfCounter;
4962  if (fBranchCount==0) return;
4963 
4964  TLeafElement* leafOfCounter = (TLeafElement*) brOfCounter->GetListOfLeaves()->At(0);
4965  TLeafElement* leaf = (TLeafElement*) GetListOfLeaves()->At(0);
4966  if (leafOfCounter && leaf) {
4967  leaf->SetLeafCount(leafOfCounter);
4968  } else {
4969  if (!leafOfCounter) {
4970  Warning("SetBranchCount", "Counter branch %s for branch %s has no leaves!", brOfCounter->GetName(), GetName());
4971  }
4972  if (!leaf) {
4973  Warning("SetBranchCount", "Branch %s has no leaves!", GetName());
4974  }
4975  }
4976 }
4977 
4978 ////////////////////////////////////////////////////////////////////////////////
4979 /// Set the branch in a mode where the object are decomposed
4980 /// (Also known as MakeClass mode).
4981 /// Return whether the setting was possible (it is not possible for
4982 /// TBranch and TBranchObject).
4983 
4985 {
4986  if (decomposeObj)
4987  SetBit(kDecomposedObj); // Same as SetBit(kMakeClass)
4988  else
4990 
4991  Int_t nbranches = fBranches.GetEntriesFast();
4992  for (Int_t i = 0; i < nbranches; ++i) {
4993  TBranchElement* branch = (TBranchElement*) fBranches[i];
4994  branch->SetMakeClass(decomposeObj);
4995  }
4996  SetReadLeavesPtr();
4997  SetFillLeavesPtr();
4998 
4999  return kTRUE;
5000 }
5001 
5002 ////////////////////////////////////////////////////////////////////////////////
5003 /// Set object this branch is pointing to.
5004 
5006 {
5007  if (TestBit(kDoNotProcess)) {
5008  return;
5009  }
5010  fObject = (char*)obj;
5011  SetAddress( &fObject );
5012 }
5013 
5014 ////////////////////////////////////////////////////////////////////////////////
5015 /// Set offset of the object (to which the data member represented by this
5016 /// branch belongs) inside its containing object (if any).
5017 
5019 {
5020  // We need to make sure that the Read and Write action's configuration
5021  // properly reflect this value.
5022 
5023  if (fReadActionSequence) {
5025  }
5026  if (fFillActionSequence) {
5028  }
5029  fOffset = offset;
5030 }
5031 
5032 ////////////////////////////////////////////////////////////////////////////////
5033 /// Set the sequence of actions needed to read the data out of the buffer.
5034 
5036 {
5037  if (fInfo == 0) {
5038  // We are called too soon. We will be called again by InitInfo
5039  return;
5040  }
5041 
5042  // Get the action sequence we need to copy for reading.
5045  if (fType == 41) {
5047  original = fInfo->GetReadMemberWiseActions(kTRUE);
5048  } else {
5049  TVirtualStreamerInfo *info = GetInfoImp();
5050  if (GetParentClass() == info->GetClass()) {
5053  } else {
5055  }
5056  } else if (GetCollectionProxy()) {
5057  // Base class and embedded objects.
5058 
5060  original = transient;
5061  }
5062  }
5063  } else if (fType == 31) {
5064  original = fInfo->GetReadMemberWiseActions(kTRUE);
5065  } else if (0<=fType && fType<=2) {
5066  // Note: this still requires the ObjectWise sequence to not be optimized!
5067  original = fInfo->GetReadMemberWiseActions(kFALSE);
5068  }
5069  if (original) {
5070  fIDs.insert(fIDs.begin(),fID); // Include the main element in the sequence.
5071  if (fReadActionSequence) delete