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