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.
5073  fIDs.erase(fIDs.begin());
5074  }
5075  delete transient;
5076 }
5077 
5078 ////////////////////////////////////////////////////////////////////////////////
5079 /// Set the ReadLeaves pointer to execute the expected operations.
5080 
5082 {
5083  if (TestBit(kDecomposedObj)) {
5085  } else if (fType == 4) {
5087  } else if (fType == 41) {
5091  } else {
5093  }
5094  } else {
5096  }
5097  } else if (fType == 3) {
5099  } else if (fType == 31) {
5101  } else if (fType < 0) {
5103  } else if (fType == 0 && fID == -1) {
5104  // top-level branch.
5106  if (hasCustomStreamer) {
5107  // We are in the case where the object did *not* have a custom
5108  // Streamer when the TTree was written but now *does* have a custom
5109  // Streamer thus we must use it.
5111  } else {
5113  }
5114  } else if (fType <= 2) {
5115  // split-class branch, base class branch or data member branch.
5116  if (fBranchCount) {
5120  } else {
5122  }
5123  } else {
5124  Fatal("SetReadLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5125  }
5126 
5128 }
5129 
5130 ////////////////////////////////////////////////////////////////////////////////
5131 /// Set the sequence of actions needed to write the data out from the buffer.
5132 
5134 {
5135  if (fInfo == 0) {
5136  // We are called too soon. We will be called again by InitInfo
5137  return;
5138  }
5139 
5140  // Get the action sequence we need to copy for reading.
5143  if (fType == 41) {
5145  original = fInfo->GetWriteMemberWiseActions(kTRUE);
5146  } else {
5147  TVirtualStreamerInfo *info = GetInfoImp();
5148  if (GetParentClass() == info->GetClass()) {
5149  //if( fTargetClass.GetClassName()[0] && fBranchClass != fTargetClass ) {
5150  // original = GetCollectionProxy()->GetConversionWriteMemberWiseActions(fBranchClass.GetClass());
5151  //} else {
5153  //}
5154  } else if (GetCollectionProxy()) {
5155  // Base class and embedded objects.
5156 
5158  original = transient;
5159  }
5160  }
5161  } else if (fType == 31) {
5162  original = fInfo->GetWriteMemberWiseActions(kTRUE);
5163  } else if (0<=fType && fType<=2) {
5164  // Note: this still requires the ObjectWise sequence to not be optimized!
5165  original = fInfo->GetWriteMemberWiseActions(kFALSE);
5166  }
5167  if (original) {
5168  fIDs.insert(fIDs.begin(),fID); // Include the main element in the sequence.
5171  fIDs.erase(fIDs.begin());
5172  }
5173  delete transient;
5174 
5175 }
5176 
5177 ////////////////////////////////////////////////////////////////////////////////
5178 /// Set the FillLeaves pointer to execute the expected operations.
5179 
5181 {
5182  if (fTree->GetMakeClass() && ((fType==3)||(fType==31))) {
5184  } else if (fType == 4) {
5186  } else if (fType == 41) {
5190  } else {
5192  }
5195  } else {
5197  }
5198  } else if (fType == 3) {
5200  } else if (fType == 31) {
5202  } else if (fType < 0) {
5204  } else if (fType <=2) {
5205  //split-class branch, base class branch, data member branch, or top-level branch.
5206  if (fBranchCount) {
5210  } else {
5212  }
5213  } else {
5214  Fatal("SetFillLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5215  }
5216 
5218 }
5219 
5220 ////////////////////////////////////////////////////////////////////////////////
5221 /// Set the name of the class of the in-memory object into which the data will
5222 /// loaded.
5223 
5225 {
5226  if (name == 0) return;
5227 
5228  if (strcmp(fTargetClass.GetClassName(),name) != 0 )
5229  {
5230  // We are changing target class, let's reset the meta information and
5231  // the sub-branches.
5232 
5233  fInfo = 0;
5234  fInit = kFALSE;
5235  fInitOffsets = kFALSE;
5236  delete fReadActionSequence;
5237  fReadActionSequence = 0;
5238  delete fFillActionSequence;
5239  fFillActionSequence = 0;
5240 
5241  Int_t nbranches = fBranches.GetEntriesFast();
5242  for (Int_t i = 0; i < nbranches; ++i) {
5244  if (sub->fTargetClass == fTargetClass ) {
5245  sub->SetTargetClass(name);
5246  }
5247  if (sub->fParentClass == fTargetClass ) {
5248  sub->SetParentClass(TClass::GetClass(name));
5249  }
5250  }
5251  fTargetClass = name;
5252  }
5253 
5254 }
5255 
5256 ////////////////////////////////////////////////////////////////////////////////
5257 /// If the branch address is not set, we set all addresses starting with
5258 /// the top level parent branch. This is required to be done in order for
5259 /// GetOffset to be correct and for GetEntry to run.
5260 
5262 {
5263  // Check to see if the user changed the branch address on us.
5264  ValidateAddress();
5265 
5266  if (fAddress || fTree->GetMakeClass()) {
5267  // -- Do nothing if already setup or if we are a MakeClass tree.
5268  return;
5269  }
5271 }
5272 
5273 ////////////////////////////////////////////////////////////////////////////////
5274 /// If the branch address is not set, we set all addresses starting with
5275 /// the top level parent branch. This is required to be done in order for
5276 /// GetOffset to be correct and for GetEntry to run.
5277 
5279 {
5281  // -- Do nothing if we have been told not to.
5282  // Or the data member in this branch is not longer part of the
5283  // parent's layout.
5284  return;
5285  }
5286 
5287  //--------------------------------------------------------------------------
5288  // Check if we are splited STL collection of pointers
5289  /////////////////////////////////////////////////////////////////////////////
5290 
5292  {
5293  TBranchElement *parent = (TBranchElement *)GetMother()->GetSubBranch( this );
5294 
5295  // Make sure the StreamerInfo is loaded and initialized.
5296  GetInfoImp();
5297 
5298  if( !parent->GetAddress() )
5299  parent->SetAddress( 0 );
5300  return;
5301  }
5302 
5303  //--------------------------------------------------------------------------
5304  // Any other case
5305  /////////////////////////////////////////////////////////////////////////////
5306 
5307  TBranchElement* mother = (TBranchElement*) GetMother();
5308  if (!mother) {
5309  return;
5310  }
5311  TClass* cl = TClass::GetClass(mother->GetClassName());
5312 
5313  // Make sure the StreamerInfo is loaded and initialized.
5314  GetInfoImp();
5315 
5316  if (!cl) {
5317  return;
5318  }
5319 
5320  if (!mother->GetAddress()) {
5321  // -- Our top-level branch has no address.
5322  Bool_t motherStatus = mother->TestBit(kDoNotProcess);
5323  mother->ResetBit(kDoNotProcess);
5324  // Note: This will allocate an object.
5325  mother->SetAddress(0);
5326  mother->SetBit(kDoNotProcess, motherStatus);
5327  }
5328 }
5329 
5330 ////////////////////////////////////////////////////////////////////////////////
5331 /// Stream an object of class TBranchElement.
5332 
5333 void TBranchElement::Streamer(TBuffer& R__b)
5334 {
5335  if (R__b.IsReading()) {
5336  R__b.ReadClassBuffer(TBranchElement::Class(), this);
5341  // The fAddress and fObject data members are not persistent,
5342  // therefore we do not own anything.
5343  // Also clear the bit possibly set by the schema evolution.
5345  // Fixup a case where the TLeafElement was missing
5346  if ((fType == 0) && (fLeaves.GetEntriesFast() == 0)) {
5347  TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
5348  leaf->SetTitle(GetTitle());
5349  fNleaves = 1;
5350  fLeaves.Add(leaf);
5351  fTree->GetListOfLeaves()->Add(leaf);
5352  }
5353  // SetReadLeavesPtr();
5354  }
5355  else {
5356  TDirectory* dirsav = fDirectory;
5357  fDirectory = 0; // to avoid recursive calls
5358  {
5359  // Save class version.
5360  Int_t classVersion = fClassVersion;
5361  // Record only positive 'version number'
5362  if (fClassVersion < 0) {
5364  }
5365  // TODO: Should we clear the kDeleteObject bit before writing?
5366  // If we did we would have to remember the old value and
5367  // put it back, we wouldn't want to forget that we owned
5368  // something just because we got written to disk.
5370  // Restore class version.
5371  fClassVersion = classVersion;
5372  }
5373  //
5374  // Mark all streamer infos used by this branch element
5375  // to be written to our output file.
5376  //
5377  {
5378  R__b.ForceWriteInfo(GetInfoImp(), kTRUE);
5379  }
5380  //
5381  // If we are a clones array master branch, or an
5382  // STL container master branch, we must also mark
5383  // the streamer infos used by the value class to
5384  // be written to our output file.
5385  //
5386  if (fType == 3) {
5387  // -- TClonesArray, counter/master branch
5388  //
5389  // We must mark the streamer info for the
5390  // value class to be written to the file.
5391  //
5392  TClass* cl = fClonesClass;
5393  if (cl) {
5394  R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
5395  }
5396  }
5397  else if (fType == 4) {
5398  // -- STL container, counter/master branch
5399  //
5400  // We must mark the streamer info for the
5401  // value class to be written to the file.
5402  //
5404  if (cp) {
5405  TClass* cl = cp->GetValueClass();
5406  if (cl) {
5407  R__b.ForceWriteInfo(cl->GetStreamerInfo(), kTRUE);
5408  }
5409  }
5410  }
5411  // If we are in a separate file, then save
5412  // ourselves as an independent key.
5413  if (!dirsav) {
5414  // Note: No need to restore fDirectory, it was already zero.
5415  return;
5416  }
5417  if (!dirsav->IsWritable()) {
5418  fDirectory = dirsav;
5419  return;
5420  }
5421  TDirectory* pdirectory = fTree->GetDirectory();
5422  if (!pdirectory) {
5423  fDirectory = dirsav;
5424  return;
5425  }
5426  const char* treeFileName = pdirectory->GetFile()->GetName();
5427  TBranch* mother = GetMother();
5428  const char* motherFileName = treeFileName;
5429  if (mother && (mother != this)) {
5430  motherFileName = mother->GetFileName();
5431  }
5432  if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
5433  dirsav->WriteTObject(this);
5434  }
5435  fDirectory = dirsav;
5436  }
5437 }
5438 
5439 ////////////////////////////////////////////////////////////////////////////////
5440 /// Split class cl into sub-branches of this branch.
5441 ///
5442 /// Create a sub-branch of this branch for each non-empty,
5443 /// non-abstract base class of cl (unless we are a sub-branch
5444 /// of a TClonesArray or an STL container, in which case we
5445 /// do *not* create a sub-branch), and for each non-split data
5446 /// member of cl.
5447 ///
5448 /// Note: We do *not* create sub-branches for base classes of cl
5449 /// if we are a sub-branch of a TClonesArray or an STL container.
5450 ///
5451 /// Note: We do *not* create sub-branches for data members which
5452 /// have a class type and which we are splitting.
5453 ///
5454 /// Note: The above rules imply that the branch heirarchy increases
5455 /// in depth only for base classes of cl (unless we are inside
5456 /// of a TClonesArray or STL container, in which case the depth
5457 /// does *not* increase, the base class is elided) and for
5458 /// TClonesArray or STL container data members (which have one
5459 /// additional level of sub-branches). The only other way the
5460 /// depth increases is when the top-level branch has a split
5461 /// class data member, in that case the constructor will create
5462 /// a sub-branch for it. In other words, the interior nodes of
5463 /// the branch tree are all either: base class nodes; split
5464 /// class nodes which are direct sub-branches of top-level nodes
5465 /// (created by TClass::Bronch usually); or TClonesArray or STL
5466 /// container master nodes.
5467 ///
5468 /// Note: The exception to the above is for the top-level branches,
5469 /// Tree::Bronch creates nodes for everything in that case,
5470 /// except for a TObject base class of a class which has the
5471 /// can ignore tobject streamer flag set.
5472 
5473 Int_t TBranchElement::Unroll(const char* name, TClass* clParent, TClass* cl, char* ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
5474 {
5475  //----------------------------------------------------------------------------
5476  // Handling the case of STL collections of pointers
5477  /////////////////////////////////////////////////////////////////////////////
5478 
5479  Int_t splitSTLP = splitlevel - (splitlevel%TTree::kSplitCollectionOfPointers);
5480  splitlevel %= TTree::kSplitCollectionOfPointers;
5481 
5482  TString branchname;
5483 
5484  if ((cl == TObject::Class()) && clParent->CanIgnoreTObjectStreamer()) {
5485  return 0;
5486  }
5487 
5488  TStreamerInfo* sinfo = fTree->BuildStreamerInfo(cl);
5489 
5490  //
5491  // Do nothing if we couldn't build the streamer info for cl.
5492  //
5493 
5494  if (!sinfo) {
5495  return 0;
5496  }
5497 
5498  Int_t ndata = sinfo->GetNelement();
5499 
5500  if ((ndata == 1) && cl->GetCollectionProxy() && !strcmp(sinfo->GetElement(0)->GetName(), "This")) {
5501  // -- Class cl is an STL collection, refuse to split it.
5502  // Question: Why? We certainly could by switching to the value class.
5503  // Partial Answer: Only the branch element constructor can split STL containers.
5504  return 1;
5505  }
5506 
5507  for (Int_t elemID = 0; elemID < ndata; ++elemID) {
5508  // -- Loop over all the streamer elements and create sub-branches as needed.
5509  TStreamerElement* elem = sinfo->GetElement(elemID);
5510  if (elem->IsA() == TStreamerArtificial::Class()) {
5511  continue;
5512  }
5513  if (elem->TestBit(TStreamerElement::kRepeat)) {
5514  continue;
5515  }
5517  continue;
5518  }
5519  Int_t offset = elem->GetOffset();
5520  // FIXME: An STL container as a base class gets TStreamerSTL as its class, so this test is not enough.
5521  // See InitializeOffsets() for the proper test.
5522  if (elem->IsA() == TStreamerBase::Class()) {
5523  // -- This is a base class of cl.
5524  TClass* clOfBase = elem->GetClassPointer();
5525  if (!clOfBase || ((clOfBase->Property() & kIsAbstract) && cl->InheritsFrom(TCollection::Class()))) {
5526  // -- Do nothing if we are one of the abstract collection (we know they have no data).
5527  return -1;
5528  }
5529  if ((btype == 31) || (btype == 41)) {
5530  // -- Elide the base-class sub-branches of a split TClonesArray or STL container.
5531  //
5532  // Note: We are eliding the base class here, that is, we never
5533  // create a branch for it, so the branch heirarchy is not
5534  // complete.
5535  // Note: The clParent parameter is the value class of the
5536  // container which we are splitting. It does not
5537  // appear in the branch heirarchy either.
5538  // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
5539  Int_t unroll = -1;
5540  if (!elem->CannotSplit() || clOfBase == TObject::Class()) {
5541  unroll = Unroll(name, clParent, clOfBase, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5542  }
5543  if (unroll < 0) {
5544  // FIXME: We could not split because we are abstract, should we be doing this?
5545  if (strlen(name)) {
5546  branchname.Form("%s.%s", name, elem->GetFullName());
5547  } else {
5548  branchname.Form("%s", elem->GetFullName());
5549  }
5550  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, 0, btype);
5551  branch->SetParentClass(clParent);
5552  fBranches.Add(branch);
5553  }
5554  } else if (clOfBase->GetListOfRealData()->GetSize()) {
5555  // -- Create a branch for a non-empty base class.
5556  if (strlen(name)) {
5557  branchname.Form("%s.%s", name, elem->GetFullName());
5558  // Elide the base class name when creating the sub-branches.
5559  // Note: The branch names for sub-branches of a base class branch
5560  // do not represent the full class heirarchy because we do
5561  // this, however it does keep the branch names for the
5562  // inherited data members simple.
5563  TBranchElement* branch = new TBranchElement(this, name, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5564  // Then reset it to the proper name.
5565  branch->SetName(branchname);
5566  branch->SetTitle(branchname);
5567  branch->SetParentClass(clParent);
5568  fBranches.Add(branch);
5569  } else {
5570  branchname.Form("%s", elem->GetFullName());
5571  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel+splitSTLP, btype);
5572  branch->SetParentClass(clParent);
5573  fBranches.Add(branch);
5574  }
5575  }
5576  } else {
5577  // -- This is a data member of cl.
5578  if (strlen(name)) {
5579  branchname.Form("%s.%s", name, elem->GetFullName());
5580  } else {
5581  branchname.Form("%s", elem->GetFullName());
5582  }
5583  if ((splitlevel > 1) && ((elem->IsA() == TStreamerObject::Class()) || (elem->IsA() == TStreamerObjectAny::Class()))) {
5584  // -- We are splitting a non-TClonesArray (may inherit from TClonesArray though), non-STL container object.
5585  //
5586  // Ignore an abstract class.
5587  // FIXME: How could an abstract class get here?
5588  // Partial answer: It is a base class. But this is a data member!
5589  TClass* elemClass = elem->GetClassPointer();
5590  if (!elemClass || elemClass->Property() & kIsAbstract) {
5591  return -1;
5592  }
5593  if (elem->CannotSplit()) {
5594  // We are not splitting.
5595  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
5596  branch->SetParentClass(clParent);
5597  fBranches.Add(branch);
5598  } else if (elemClass->InheritsFrom(TClonesArray::Class())) {
5599  // Splitting something derived from TClonesArray.
5600  Int_t subSplitlevel = splitlevel-1;
5601  if (btype == 31 || btype == 41 || elem->CannotSplit()) {
5602  // -- We split the sub-branches of a TClonesArray or an STL container only once.
5603  subSplitlevel = 0;
5604  }
5605  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel, btype);
5606  branch->SetParentClass(clParent);
5607  fBranches.Add(branch);
5608  } else {
5609  // Splitting a normal class.
5610  // FIXME: We are eliding the class we are splitting here,
5611  // i.e., we do not create a branch for it, so the
5612  // branch heirarchy does not match the class heirarchy.
5613  // Note: clParent is the class which contains a data member of
5614  // the class type which we are splitting.
5615  // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
5616  Int_t unroll = Unroll(branchname, clParent, elemClass, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
5617  if (unroll < 0) {
5618  // FIXME: We could not split because we are abstract, should we be doing this?
5619  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
5620  branch->SetParentClass(clParent);
5621  fBranches.Add(branch);
5622  }
5623  }
5624  }
5625  else if( elem->GetClassPointer() &&
5626  elem->GetClassPointer()->GetCollectionProxy() &&
5628  splitSTLP && fType != 4 )
5629  {
5630 
5631  TBranchSTL* branch = new TBranchSTL( this, branchname,
5633  basketsize, splitlevel - 1+splitSTLP, sinfo, elemID );
5634  branch->SetAddress( ptr+offset );
5635  fBranches.Add( branch );
5636  }
5637  else if ((elem->IsA() == TStreamerSTL::Class()) && !elem->IsaPointer()) {
5638  // -- We have an STL container.
5639  // Question: What if splitlevel == 0 here?
5640  // Answer: then we should not be here.
5641  Int_t subSplitlevel = splitlevel - 1;
5642  if ((btype == 31) || (btype == 41) || elem->CannotSplit()) {
5643  // -- We split the sub-branches of a TClonesArray or an STL container only once.
5644  subSplitlevel = 0;
5645  }
5646  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, subSplitlevel+splitSTLP, btype);
5647  branch->SetParentClass(clParent);
5648  fBranches.Add(branch);
5649  } else if (((btype != 31) && (btype != 41)) && ptr && ((elem->GetClassPointer() == TClonesArray::Class()) || ((elem->IsA() == TStreamerSTL::Class()) && !elem->CannotSplit()))) {
5650  // -- We have a TClonesArray.
5651  // FIXME: We could get a ptr to a TClonesArray here by mistake.
5652  // Question: What if splitlevel == 0 here?
5653  // Answer: then we should not be here.
5654  // Note: ptr may be null in case of a TClonesArray inside another
5655  // TClonesArray or STL container, see the else clause.
5656  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, splitlevel-1+splitSTLP, btype);
5657  branch->SetParentClass(clParent);
5658  fBranches.Add(branch);
5659  } else {
5660  // -- We are not going to split this element any farther.
5661  TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, 0, basketsize, splitSTLP, btype);
5662  branch->SetType(btype);
5663  branch->SetParentClass(clParent);
5664  fBranches.Add(branch);
5665  }
5666  }
5667  }
5668 
5669  return 1;
5670 }
5671 
5672 ////////////////////////////////////////////////////////////////////////////////
5673 /// Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
5674 /// with the current value of fTree->GetCurrentFile unless this branch has been
5675 /// redirected to a different file. Also update the sub-branches.
5676 
5678 {
5679  // The BranchCount and BranchCount2 are part of higher level branches' list of
5680  // branches.
5681  // if (fBranchCount) fBranchCount->UpdateFile();
5682  // if (fBranchCount2) fBranchCount2->UpdateFile();
5684 }
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is &#39;source&#39;.
const int ndata
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
TClassRef fTargetClass
! Reference to the target in-memory class
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Int_t GetDefaultEntryOffsetLen() const
Definition: TTree.h:389
void SetBufferOffset(Int_t offset=0)
Definition: TBuffer.h:90
virtual Int_t GetCollectionType() const =0
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
Bool_t IsReading() const
Definition: TBuffer.h:83
void FillLeavesAssociativeCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual void WriteFloat16(Float_t *f, TStreamerElement *ele=0)=0
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method). ...
Definition: TClass.cxx:5592
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2240
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2552
An array of TObjects.
Definition: TObjArray.h:39
TBranchElement * fBranchCount2
pointer to secondary branchcount branch
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
const char * GetTypeNameBasic() const
Return type name of this element in case the type name is not a standard basic type, return the basic type name known to CINT.
virtual void * Allocate(UInt_t n, Bool_t forceDelete)=0
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
T GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const
Return value of element i in object at pointer.
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2664
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
void PrintValue(Int_t i) const
Prints values of leaves.
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:51
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2061
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name &#39;searchname&#39;.
Int_t fOffset
Offset of this branch.
Definition: TBranch.h:74
virtual TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Int_t version)=0
long long Long64_t
Definition: RtypesCore.h:69
virtual Int_t GetProperties() const
Int_t GetType() const
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const
Return the StreamerElement of "datamember" inside our class or any of its base classes.
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
virtual TClass * GetClass() const =0
Int_t GetNevBufSize() const
Definition: TBasket.h:80
Long64_t fEntries
Number of entries.
Definition: TBranch.h:84
float Float_t
Definition: RtypesCore.h:53
virtual void InitInfo()
Init the streamer info for the branch class, try to compensate for class code unload/reload and schem...
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for version number &#39;version&#39; to this clas...
Definition: TClass.cxx:6645
float Size_t
Definition: RtypesCore.h:83
virtual TStreamerInfoActions::TActionSequence * GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version)=0
const char Option_t
Definition: RtypesCore.h:62
Double_t GetValue(Int_t i, Int_t len, Bool_t subarr=kFALSE) const
virtual TClass * GetValueClass() const =0
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
double T(double x)
Definition: ChebyshevPol.h:34
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
TString fParentName
Name of parent class.
virtual void WriteDouble32(Double_t *d, TStreamerElement *ele=0)=0
ReadLeaves_t fReadLeaves
! Pointer to the ReadLeaves implementation to use.
Definition: TBranch.h:107
TStreamerElement * GetElement(Int_t id) const
const char * GetIconName() const
Return icon name depending on type of branch element.
T GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
virtual void SetLeafCount(TLeaf *leaf)
Set the leaf count of this leaf.
Definition: TLeafElement.h:60
virtual void Reset(Option_t *option="")
Reset a Branch.
unsigned short UShort_t
Definition: RtypesCore.h:36
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
Int_t GetMakeClass() const
Definition: TTree.h:424
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:1572
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist...
Definition: TClass.cxx:4368
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
virtual Int_t GetEntries() const
Definition: TCollection.h:92
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual void Commit(void *)=0
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name &#39;searchname&#39;.
Definition: TBranch.cxx:953
Int_t GetNdata() const
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
void FillLeavesCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition: TClass.cxx:2839
void SetName(const char *new_name)
Definition: TClassRef.h:70
Bool_t IsFolder() const
Return kTRUE if more than one leaf or browsables, kFALSE otherwise.
Definition: TBranch.cxx:1672
virtual TClass * GetCollectionClass() const
const Int_t kBranchObject
Definition: TBranch.h:54
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
#define R__ASSERT(e)
Definition: TError.h:98
#define gROOT
Definition: TROOT.h:364
void FillLeavesCustomStreamer(TBuffer &b)
Write leaves into i/o buffers for this branch.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3570
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Long64_t GetDebugMin() const
Definition: TTree.h:391
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
Int_t GetOffset() const
Definition: TBranch.h:168
void PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
Need to pushd/pop fOnfileObject.
UInt_t fElemId
Identifier of the TStreamerElement.
TObjArray fBaskets
-> List of baskets of this branch
Definition: TBranch.h:90
Basic string class.
Definition: TString.h:137
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2822
virtual void SetAddress(void *addobj)
Point this branch at an object.
static void R__CleanName(std::string &name)
Remove trailing dimensions and make sure there is a trailing dot.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const char * GetClassName()
Definition: TClassRef.h:74
virtual void Clear(const char *opt="")=0
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void * New() const
virtual void ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t force)=0
void SetReadActionSequence()
Set the sequence of actions needed to read the data out of the buffer.
Int_t fNleaves
! Number of leaves
Definition: TBranch.h:78
Int_t GetNelement() const
void ReadLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
The addressing set have been called for this branch.
TObjArray fLeaves
-> List of leaves of this branch
Definition: TBranch.h:89
void MapObject(const TObject *obj, UInt_t offset=1)
Add object to the fMap container.
TString & Prepend(const char *cs)
Definition: TString.h:604
Long64_t * fBasketSeek
[fMaxBaskets] Addresses of baskets on file
Definition: TBranch.h:93
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
const char * Class
Definition: TXMLSetup.cxx:64
UInt_t fCheckSum
CheckSum of class.
void FillLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
More explicit alias for kMakeClass.
virtual EDataType GetType() const =0
void SetupAddressesImpl()
If the branch address is not set, we set all addresses starting with the top level parent branch...
virtual Int_t GetMaximum() const
Return maximum count value of the branchcount if any.
TObject ** GetObjectRef() const
Definition: TObjArray.h:70
TStreamerInfoActions::TActionSequence * fFillActionSequence
! Set of actions to be executed to write the data to the basket.
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
void PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax=1000) const
print value of element i in object at pointer The function may be called in two ways: -method1 len < ...
Bool_t fInit
! Initialization flag for branch assignment
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
static TActionSequence * CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
virtual TStreamerElement * GetElement(Int_t id) const =0
TClass * GetClass() const
Definition: TClassRef.h:75
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
void ReadLeavesClones(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t * fBasketBytes
[fMaxBaskets] Length of baskets on file
Definition: TBranch.h:91
virtual TList * GetBrowsables()
Returns (and, if 0, creates) browsable objects for this branch See TVirtualBranchBrowsable::FillListO...
Definition: TBranch.cxx:1170
TActionSequence * CreateSubSequence(const std::vector< Int_t > &element_ids, size_t offset)
Long64_t fEntryNumber
Current entry number (last one filled in this branch)
Definition: TBranch.h:73
virtual Bool_t CannotSplit() const
Returns true if the element cannot be split, false otherwise.
void ReadLeavesCustomStreamer(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t Length() const
Definition: TBuffer.h:96
void FillLeavesCollection(TBuffer &b)
Write leaves into i/o buffers for this branch.
const Int_t kBranchAny
Definition: TBranch.h:55
void ReadLeavesMemberBranchCount(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t fWriteBasket
Last basket number written.
Definition: TBranch.h:72
Int_t fNdata
! Number of data in this branch
char * GetObjectAt(UInt_t ind) const
Definition: TVirtualArray.h:38
friend class TClonesArray
Definition: TObject.h:198
TVirtualArray * fOnfileObject
! Place holder for the onfile representation of data members.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
void SetFillActionSequence()
Set the sequence of actions needed to write the data out from the buffer.
TStreamerInfoActions::TActionSequence * fReadActionSequence
! Set of actions to be executed to extract the data from the basket.
virtual void SetAddress(void *addr)
We are the top level branch.
Definition: TBranchSTL.cxx:682
virtual Bool_t IsWritable() const
Definition: TDirectory.h:171
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
virtual Long64_t GetReadEntry() const
Definition: TTree.h:436
Int_t fMaximum
Maximum entries for a TClonesArray or variable array.
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition: TClass.cxx:4451
void ReadLeavesCollectionSplitPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process&#39;s memory.
Definition: TClass.cxx:5557
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:907
void BuildTitle(const char *name)
Set branch and leaf name and title in the case of a container sub-branch.
virtual void ResetDeleteObject()
Release ownership of any allocated objects.
void FillLeavesClones(TBuffer &b)
Write leaves into i/o buffers for this branch.
void FillLeavesClonesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual void SetBasketSize(Int_t buffsize)
Reset the basket size for all sub-branches of this branch element.
Bool_t IsAutoDelete() const
Return kTRUE if an existing object in a TBranchObject must be deleted.
Definition: TBranch.cxx:1664
void ReadLeavesMemberCounter(TBuffer &b)
Read leaves into i/o buffers for this branch.
const Int_t kDoNotProcess
Definition: TBranch.h:52
TString & Append(const char *cs)
Definition: TString.h:492
Int_t * fBranchOffset
! Sub-Branch offsets with respect to current transient class
virtual void Destructor(void *p, Bool_t dtorOnly=kFALSE) const
Long_t GetThisOffset() const
Definition: TRealData.h:59
TVirtualCollectionProxy * fCollProxy
! collection interface (if any)
static const std::string pattern("pattern")
Int_t GetID() const
virtual Bool_t SetMakeClass(Bool_t decomposeObj=kTRUE)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode)...
virtual void Browse(TBrowser *b)
Browse the branch content.
Version_t fClassVersion
Version number of class.
TObjArray * GetListOfBranches()
Definition: TBranch.h:178
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
Int_t fMaxBaskets
Maximum number of Baskets so far.
Definition: TBranch.h:75
T GetTypedValue(Int_t i, Int_t len, Bool_t subarr=kFALSE) const
void FillLeavesMemberCounter(TBuffer &b)
Write leaves into i/o buffers for this branch.
XFontStruct * id
Definition: TGX11.cxx:108
void FillLeavesMemberBranchCount(TBuffer &b)
Write leaves into i/o buffers for this branch.
TString fClassName
Class name of referenced object.
virtual void ls(Option_t *option="") const
Print the content of the element.
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of a BranchElement and return total number of bytes.
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:447
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:124
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:33
void SetFillLeavesPtr()
Set the FillLeaves pointer to execute the expected operations.
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations)
Bool_t IsMissingCollection() const
Detect a collection written using a zero pointer in old versions of root.
virtual TFile * GetFile() const
Definition: TDirectory.h:155
virtual const char * GetClonesName() const
Int_t fSplitLevel
Branch split level.
Definition: TBranch.h:77
TString fClonesName
Name of class in TClonesArray (if any)
virtual void ResetAddress()
Set branch address to zero and free all allocated memory.
void ReadLeavesClonesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
T GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
A doubly linked list.
Definition: TList.h:47
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:1977
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4869
Int_t GetType() const
Definition: TDataType.h:70
virtual Int_t Fill()
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:737
void FillLeavesMakeClass(TBuffer &b)
Write leaves into i/o buffers for this branch.
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1951
Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)
Read one collection of objects from the buffer using the StreamerInfoLoopAction.
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
void(TBranch::* ReadLeaves_t)(TBuffer &b)
Definition: TBranch.h:106
Int_t fID
element serial number in fInfo
void SetParentClass(TClass *clparent)
void ValidateAddress() const
virtual char * GetAddress() const
Get the branch address.
virtual const char * GetTypeName() const
Return type name of element in the branch.
virtual Int_t Fill()
Loop on all leaves of this branch to fill the basket buffer.
Small helper class to generically acquire and release iterators.
TClass * GetClass() const
Int_t fBasketSize
Initial Size of Basket Buffer.
Definition: TBranch.h:70
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition: TClass.cxx:6625
void ReadLeavesCollection(TBuffer &b)
Read leaves into i/o buffers for this branch.
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:26
UInt_t GetCheckSum() const
virtual void SetType(Int_t btype)
virtual Int_t ApplySequence(const TStreamerInfoActions::TActionSequence &sequence, void *object)=0
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
char * GetObject() const
Return a pointer to our object.
TClassRef fParentClass
! Reference to class definition in fParentName
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Int_t GetLast() const
Definition: TBasket.h:81
virtual Bool_t HasPointers() const =0
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
static TActionSequence * CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
Create the bundle of the actions necessary for the streaming memberwise of the content described by &#39;...
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5071
TBranchElement * fBranchCount
pointer to primary branchcount branch
Int_t fStreamerType
branch streamer type
TClass * GetParentClass()
Return a pointer to the parent class of the branch element.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
FillLeaves_t fFillLeaves
! Pointer to the FillLeaves implementation to use.
Definition: TBranch.h:109
virtual void * GetValuePointer() const
Returns pointer to first data element of this branch.
unsigned int UInt_t
Definition: RtypesCore.h:42
TMarker * m
Definition: textangle.C:8
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
void SetReadLeavesPtr()
Set the ReadLeaves pointer to execute the expected operations.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
const Handle_t kNone
Definition: GuiTypes.h:89
Int_t Debug() const
Definition: TTree.h:365
Ssiz_t Length() const
Definition: TString.h:390
virtual TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions()=0
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
void ReadLeavesImpl(TBuffer &b)
Unconfiguration Read Leave function.
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
void Init(TTree *tree, TBranch *parent, const char *name, TStreamerInfo *sinfo, Int_t id, char *pointer, Int_t basketsize=32000, Int_t splitlevel=0, Int_t btype=0)
Init when the branch object is not a TClonesArray nor an STL container.
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
short Short_t
Definition: RtypesCore.h:35
TClassRef fCurrentClass
! Reference to current (transient) class definition
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:34
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1217
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:358
Int_t * GetEntryOffset() const
Definition: TBasket.h:77
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
long double LongDouble_t
Definition: RtypesCore.h:57
TClassRef fBranchClass
! Reference to class definition in fClassName
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2811
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:381
const char * GetFileName() const
Definition: TBranch.h:167
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4610
TStreamerInfoActions::TActionSequence * GetReadMemberWiseActions(Bool_t forCollection)
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5683
TString fName
Definition: TNamed.h:36
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=0) const
Definition: TClass.h:540
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
A TLeaf for the general case when using the branches created via a TStreamerInfo (i.e.
Definition: TLeafElement.h:34
virtual Int_t GetLenStatic() const
Definition: TLeaf.h:74
A Branch for the case of an object.
#define Printf
Definition: TGeoToOCC.h:18
virtual void SetRequestedEntry(Long64_t entry)
Definition: TBranchRef.h:55
PyObject * fType
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2108
T GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
virtual void ReadFloat16(Float_t *f, TStreamerElement *ele=0)=0
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
long Long_t
Definition: RtypesCore.h:50
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
int Ssiz_t
Definition: RtypesCore.h:63
void SetBranchCount(TBranchElement *bre)
Set the branch counter for this branch.
virtual Int_t ApplySequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection)=0
Int_t fSTLtype
! STL container type
Version_t GetClassVersion() const
Definition: TClass.h:382
virtual void MapObject(const TObject *obj, UInt_t offset=1)=0
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual TVirtualArray * PopDataCache()
Pop and Return the &#39;current&#39; data cache area from the list of area to be used for temporarily store &#39;...
Definition: TBuffer.cxx:350
void Print(Option_t *="") const
This method must be overridden when a class wants to print itself.
virtual Int_t GetMaximum() const
Definition: TLeaf.h:76
#define ClassImp(name)
Definition: Rtypes.h:279
Int_t fReadBasket
! Current basket number when reading
Definition: TBranch.h:79
Bool_t IsZombie() const
Definition: TObject.h:120
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2030
double Double_t
Definition: RtypesCore.h:55
We are the owner of fObject.
virtual TObjArray * GetElements() const =0
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:865
Bool_t IsFolder() const
Return kTRUE if more than one leaf, kFALSE otherwise.
void FillLeavesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
Describe directory structure in memory.
Definition: TDirectory.h:44
TDirectory * GetDirectory() const
Definition: TTree.h:392
virtual Bool_t IsaPointer() const
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
virtual const char * GetFullName() const
Return element name including dimensions, if any Note that this function stores the name into a stati...
int type
Definition: TGX11.cxx:120
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
unsigned long long ULong64_t
Definition: RtypesCore.h:70
TList * GetListOfRealData() const
Definition: TClass.h:405
unsigned long ULong_t
Definition: RtypesCore.h:51
void SetBranchCount2(TBranchElement *bre)
TStreamerInfo * GetInfoImp() const
Get streamer info for the branch class.
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:367
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
const char * GetCountName() const
Int_t fBranchID
! ID number assigned by a TRefTable.
std::vector< Int_t > fIDs
! List of the serial number of all the StreamerInfo to be used.
EDataType
Definition: TDataType.h:30
TBranchElement()
Default and I/O constructor.
virtual void * At(UInt_t idx)=0
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual Int_t SetParent(const TObject *obj, Int_t branchID)
Set the current parent branch.
Definition: TBranchRef.cxx:212
#define R__LOCKGUARD(mutex)
TTree * fTree
! Pointer to Tree header
Definition: TBranch.h:94
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:179
virtual void PushDataCache(TVirtualArray *)
Push a new data cache area onto the list of area to be used for temporarily store &#39;missing&#39; data memb...
Definition: TBuffer.cxx:331
TDirectory * fDirectory
! Pointer to directory where this branch buffers are stored
Definition: TBranch.h:98
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2893
TCanvas * slash()
Definition: slash.C:1
TClassRef fClonesClass
! Reference to class definition in fClonesName
UInt_t GetCheckSum()
virtual void SetOffset(Int_t offset)
Set offset of the object (to which the data member represented by this branch belongs) inside its con...
Bool_t IsPersistent() const
Definition: TDataMember.h:89
TClass * GetClass() const
Definition: TClonesArray.h:57
void ReadLeavesMakeClass(TBuffer &b)
Read leaves into i/o buffers for this branch.
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
virtual void ReadDouble32(Double_t *d, TStreamerElement *ele=0)=0
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
Int_t GetNewType() const
virtual UInt_t Size() const =0
Bool_t fInitOffsets
! Initialization flag to not endlessly recalculate offsets
TClassRef is used to implement a permanent reference to a TClass object.
Definition: TClassRef.h:33
char Char_t
Definition: RtypesCore.h:29
Int_t GetClassVersion() const
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5583
Long64_t GetEntries() const
Definition: TBranch.h:183
virtual void Print(Option_t *option="") const
Print branch parameters.
An array of clone (identical) objects.
Definition: TClonesArray.h:32
Long64_t * fBasketEntry
[fMaxBaskets] Table of first entry in each basket
Definition: TBranch.h:92
virtual ~TBranchElement()
Destructor.
static void SwitchContainer(TObjArray *)
Modify the container type of the branches.
void FillLeavesCollectionSplitPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
const char * GetTypeName() const
virtual void ExpandCreateFast(Int_t n)
Expand or shrink the array to n elements and create the clone objects by calling their default ctor...
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
We are the owner of fOnfileObject.
#define R__unlikely(expr)
Definition: RConfig.h:532
const char * GetCountName() const
Int_t GetClassVersion()
TClass * GetNewClass() const
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:1936
void FillLeavesImpl(TBuffer &b)
Unconfiguration Fill Leave function.
TVirtualCollectionIterators * fWriteIterators
! holds the read (non-staging) iterators when the branch is of fType==4 and associative containers...
void(TBranch::* FillLeaves_t)(TBuffer &b)
Definition: TBranch.h:108
Long64_t fReadEntry
! Current entry number when reading
Definition: TBranch.h:80
Int_t fType
branch type
Long64_t GetReadEntry() const
Definition: TBranch.h:170
virtual TClass * GetClass() const
TVirtualCollectionIterators * fIterators
! holds the iterators when the branch is of fType==4.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
TBranch * fMother
! Pointer to top-level parent branch in the tree.
Definition: TBranch.h:95
TTree * GetTree() const
Definition: TBranch.h:184
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
#define gPad
Definition: TVirtualPad.h:289
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
Bool_t GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
virtual const char * GetParentName() const
Definition: tree.py:1
void PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax=1000) const
Print value of element i in a TClonesArray.
void SetSize(UInt_t size)
Definition: TVirtualArray.h:40
void Add(TObject *obj)
Definition: TObjArray.h:75
char * fObject
! Pointer to object at *fAddress
A TTree object has a header with a name and a title.
Definition: TTree.h:98
Int_t fEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TBranch.h:71
double result[121]
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3233
void ResetBit(UInt_t f)
Definition: TObject.h:156
unsigned char UChar_t
Definition: RtypesCore.h:34
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1852
#define R__LOCKGUARD_IMT2(mutex)
Definition: first.py:1
TObjArray fBranches
-> List of Branches of this branch
Definition: TBranch.h:88
const int nn
Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition: TBrowser.h:108
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:6073
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
virtual Int_t GetSize() const
Definition: TCollection.h:95
A TTree is a list of TBranches.
Definition: TBranch.h:58
Abstract Interface class describing Streamer information for one class.
Int_t fCompress
Compression level and algorithm.
Definition: TBranch.h:69
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
Int_t GetOffset() const
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1739
TString fFileName
Name of file where buffers are stored ("" if in same file as Tree header)
Definition: TBranch.h:99
Base class of the Configurations.
TBranch * fParent
! Pointer to parent branch.
Definition: TBranch.h:96
TVirtualCollectionPtrIterators * fPtrIterators
! holds the iterators when the branch is of fType==4 and it is a split collection of pointers...
Int_t GetType() const
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Copy the argument.
Definition: TClass.cxx:2398
const Int_t n
Definition: legend1.C:16
Int_t GetStreamerType() const
TStreamerInfo * fInfo
! Pointer to StreamerInfo
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
Definition: TClass.cxx:3287
void ReadLeavesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1551
char name[80]
Definition: TGX11.cxx:109
virtual void InitializeOffsets()
Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a containe...
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
virtual const char * GetName() const
Return name of this collection.
TStreamerInfoActions::TActionSequence * GetWriteMemberWiseActions(Bool_t forCollection)
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
Int_t GetCompressionSettings() const
Definition: TFile.h:372
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
TClass * GetClass() const
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:418
virtual TVirtualCollectionProxy * Generate() const =0
void ReadLeavesCollectionMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4714
void ReleaseObject()
Delete any object we may have allocated on a previous call to SetAddress.
const char * Data() const
Definition: TString.h:349
virtual void SetAutoDelete(Bool_t autodel=kTRUE)
Set the automatic delete bit.
Definition: TBranch.cxx:2095
char * fAddress
! Address of 1st leaf (variable or object)
Definition: TBranch.h:97