Logo ROOT   6.14/05
Reference Guide
TBranchProxy.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Philippe Canal 13/05/2003
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun, Fons Rademakers and al. *
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 ROOT::Detail::TBranchProxy
13 Base class for all the proxy object. It includes the imeplemtation
14 of the autoloading of branches as well as all the generic setup routine.
15 */
16 
17 #include "TBranchProxy.h"
18 #include "TLeaf.h"
19 #include "TBranchElement.h"
20 #include "TStreamerElement.h"
21 #include "TStreamerInfo.h"
22 
24 
25 using namespace ROOT::Internal;
26 
28  fDirector(0), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
29  fHasLeafCount(false), fBranchName(""), fParent(0), fDataMember(""),
30  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
31  fBranch(0), fBranchCount(0),
32  fLastTree(0), fRead(-1), fWhere(0),fCollection(0), fCurrentTreeNumber(-1)
33 {
34  // Constructor.
35 };
36 
38  const char* name) :
39  fDirector(boss), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
40  fHasLeafCount(false), fBranchName(top), fParent(0), fDataMember(""),
42  fBranch(0), fBranchCount(0),
44 {
45  // Constructor.
46 
47  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.' && name) {
48  ((TString&)fBranchName).Append(".");
49  }
50  if (name) ((TString&)fBranchName).Append(name);
51  boss->Attach(this);
52 }
53 
54 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, const char *top, const char *name, const char *membername) :
55  fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
56  fHasLeafCount(false), fBranchName(top), fParent(0), fDataMember(membername),
58  fBranch(0), fBranchCount(0),
60 {
61  // Constructor.
62 
63  if (name && strlen(name)) {
64  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
65  ((TString&)fBranchName).Append(".");
66  }
67  ((TString&)fBranchName).Append(name);
68  }
69  boss->Attach(this);
70 }
71 
72 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, Detail::TBranchProxy *parent, const char* membername, const char* top,
73  const char* name) :
74  fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
75  fHasLeafCount(false), fBranchName(top), fParent(parent), fDataMember(membername),
77  fBranch(0), fBranchCount(0),
79 {
80  // Constructor.
81 
82  if (name && strlen(name)) {
83  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
84  ((TString&)fBranchName).Append(".");
85  }
86  ((TString&)fBranchName).Append(name);
87  }
88  boss->Attach(this);
89 }
90 
92  fDirector(boss), fInitialized(false), fIsMember(membername != 0 && membername[0]), fIsClone(false), fIsaPointer(false),
93  fHasLeafCount(false), fBranchName(branch->GetName()), fParent(0), fDataMember(membername),
95  fBranch(0), fBranchCount(0),
97 {
98  // Constructor.
99 
100  boss->Attach(this);
101 }
102 
103 /// For a fullBranchName that might contain a leading friend tree path (but
104 /// access elements designating a leaf), but the leaf name such that it matches
105 /// the "path" to branch.
106 static std::string GetFriendBranchName(TTree* directorTree, TBranch* branch, const char* fullBranchName)
107 {
108  if (directorTree == branch->GetTree())
109  return branch->GetName();
110 
111  // Friend case:
112  std::string sFullBranchName = fullBranchName;
113  std::string::size_type pos = sFullBranchName.rfind(branch->GetName());
114  if (pos != std::string::npos) {
115  sFullBranchName.erase(pos);
116  sFullBranchName += branch->GetName();
117  }
118  return sFullBranchName;
119 }
120 
121 /// Constructor taking the branch name, possibly of a friended tree.
122 /// Used by TTreeReaderValue in place of TFriendProxy.
123 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, const char* branchname, TBranch* branch, const char* membername) :
124  fDirector(boss), fInitialized(false), fIsMember(membername != 0 && membername[0]), fIsClone(false), fIsaPointer(false),
125  fHasLeafCount(false), fBranchName(GetFriendBranchName(boss->GetTree(), branch, branchname)), fParent(0), fDataMember(membername),
127  fBranch(0), fBranchCount(0),
129 {
130  // Constructor.
131 
132  boss->Attach(this);
133 }
134 
136 {
137  // Typical Destructor
138 }
139 
141 {
142  // Completely reset the object.
143 
144  fWhere = 0;
145  fBranch = 0;
146  fBranchCount = 0;
147  fRead = -1;
148  fClass = 0;
149  fElement = 0;
150  fMemberOffset = 0;
151  fOffset = 0;
152  fArrayLength = 1;
153  fIsClone = false;
154  fInitialized = false;
155  fHasLeafCount = false;
156  fLastTree = 0;
157  delete fCollection;
158  fCollection = 0;
159  fCurrentTreeNumber = -1;
160 }
161 
163 {
164  // Display the content of the object
165 
166  std::cout << "fBranchName " << fBranchName << std::endl;
167  //std::cout << "fTree " << fDirector->fTree << std::endl;
168  std::cout << "fBranch " << fBranch << std::endl;
169  if (fBranchCount) std::cout << "fBranchCount " << fBranchCount << std::endl;
170 }
171 
173 {
174  // Initialize/cache the necessary information.
175 
176  // Should we check the type?
177 
178  if (!fDirector->GetTree()) {
179  return false;
180  }
181  if (fParent) {
182 
183  if (!fParent->Setup()) {
184  return false;
185  }
186 
187  TClass *pcl = fParent->GetClass();
188  R__ASSERT(pcl);
189 
190  if (pcl==TClonesArray::Class()) {
191  // We always skip the clones array
192 
194  if (i<0) fDirector->SetReadEntry(0);
195  if (fParent->Read()) {
196  if (i<0) fDirector->SetReadEntry(i);
197 
198  TClonesArray *clones;
199  clones = (TClonesArray*)fParent->GetStart();
200 
201  if (clones) pcl = clones->GetClass();
202  }
203  } else if (pcl->GetCollectionProxy()) {
204  // We always skip the collections.
205 
206  if (fCollection) delete fCollection;
208  pcl = fCollection->GetValueClass();
209  if (pcl == 0) {
210  // coverity[dereference] fparent is checked jus a bit earlier and can not be null here
211  Error("Setup","Not finding TClass for collecion for the data member %s seems no longer be in class %s",fDataMember.Data(),fParent->GetClass()->GetName());
212  return false;
213  }
214  }
215 
217  if (fElement == 0) {
218  Error("Setup","Data member %s seems no longer be in class %s",fDataMember.Data(),pcl->GetName());
219  return false;
220  }
221 
224 
225 
227 
229 
231 
232  fWhere = fParent->fWhere; // not really used ... it is reset by GetStart and GetClStart
233 
234  if (fParent->IsaPointer()) {
235  // fprintf(stderr,"non-split pointer de-referencing non implemented yet \n");
236  // nothing to do!
237  } else {
238  // Accumulate offsets.
239  // or not!? fOffset = fMemberOffset = fMemberOffset + fParent->fOffset;
240  }
241 
242  // This is not sufficient for following pointers
243 
244  } else if (!fBranch || fCurrentTreeNumber != fDirector->GetTree()->GetTreeNumber() || fLastTree != fDirector->GetTree()) {
245 
246  // This does not allow (yet) to precede the branch name with
247  // its mother's name
248  fBranch = fDirector->GetTree()->GetBranch(fBranchName.Data());
249  if (!fBranch) return false;
250 
251  {
252  // Calculate fBranchCount for a leaf.
253  TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
254  if (leaf) leaf = leaf->GetLeafCount();
255  if (leaf) {
256  fBranchCount = leaf->GetBranch();
257  // fprintf(stderr,"for leaf %s setting up leafcount %s branchcount %s\n",
258  // fBranch->GetName(),leaf->GetName(),fBranchCount->GetName());
259  //fBranchCount->Print();
260  }
261  }
262 
263  fWhere = (double*)fBranch->GetAddress();
264 
265  if (!fWhere && fBranch->IsA()==TBranchElement::Class()
266  && ((TBranchElement*)fBranch)->GetMother()) {
267 
269 
270  be->GetMother()->SetAddress(0);
271  fWhere = (double*)fBranch->GetAddress();
272 
273  }
274  if (fBranch->IsA()==TBranch::Class()) {
275  TLeaf *leaf2 = nullptr;
276  if (fDataMember.Length()) {
277  leaf2 = fBranch->GetLeaf(fDataMember);
278  } else if (!fWhere) {
279  leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
280  fWhere = leaf2->GetValuePointer();
281  }
282  if (leaf2) {
283  fWhere = leaf2->GetValuePointer();
284  fArrayLength = leaf2->GetLen();
285  if (leaf2->GetLeafCount()) {
286  fLeafCount = leaf2->GetLeafCount();
287  fHasLeafCount = true;
288  }
289  }
290  }
291 
292  if (!fWhere) {
293  fBranch->SetAddress(0);
294  fWhere = (double*)fBranch->GetAddress();
295  }
296 
297 
298  if (fWhere && fBranch->IsA()==TBranchElement::Class()) {
299 
301 
302  TStreamerInfo * info = be->GetInfo();
303  Int_t id = be->GetID();
304  if (id>=0) {
305  fOffset = info->GetElementOffset(id);
306  fElement = (TStreamerElement*)info->GetElements()->At(id);
309 
310  if ((fIsMember || (be->GetType()!=3 && be->GetType() !=4))
311  && (be->GetType()!=31 && be->GetType()!=41)) {
312 
313  if (fClass==TClonesArray::Class()) {
314  Int_t i = be->GetTree()->GetReadEntry();
315  if (i<0) i = 0;
316  be->GetEntry(i);
317 
318  TClonesArray *clones;
319  if ( fIsMember && be->GetType()==3 ) {
320  clones = (TClonesArray*)be->GetObject();
321  } else if (fIsaPointer) {
322  clones = (TClonesArray*)*(void**)((char*)fWhere+fOffset);
323  } else {
324  clones = (TClonesArray*)((char*)fWhere+fOffset);
325  }
326  if (!fIsMember) fIsClone = true;
327  fClass = clones->GetClass();
328  } else if (fClass && fClass->GetCollectionProxy()) {
329  delete fCollection;
332  }
333 
334  }
335  if (fClass) fClassName = fClass->GetName();
336  } else {
337  fClassName = be->GetClassName();
339  }
340 
341  if (be->GetType()==3) {
342  // top level TClonesArray
343 
344  if (!fIsMember) fIsClone = true;
345  fIsaPointer = false;
346  fWhere = be->GetObject();
347 
348  } else if (be->GetType()==4) {
349  // top level TClonesArray
350 
352  fIsaPointer = false;
353  fWhere = be->GetObject();
354 
355  } else if (id<0) {
356  // top level object
357 
358  fIsaPointer = false;
359  fWhere = be->GetObject();
360 
361  } else if (be->GetType()==41) {
362 
364  fWhere = be->GetObject();
365  fOffset += be->GetOffset();
366 
367  } else if (be->GetType()==31) {
368 
369  fWhere = be->GetObject();
370  fOffset += be->GetOffset();
371 
372  } else if (be->GetType()==2) {
373  // this might also be the right path for GetType()==1
374 
375  fWhere = be->GetObject();
376 
377  } else {
378 
379  // fWhere = ((unsigned char*)fWhere) + fOffset;
380  fWhere = ((unsigned char*)be->GetObject()) + fOffset;
381 
382  }
383  } else {
386  }
387 
388 
389  /*
390  fClassName = fBranch->GetClassName(); // What about TClonesArray?
391  if ( fBranch->IsA()==TBranchElement::Class() &&
392  ((TBranchElement*)fBranch)->GetType()==31 ||((TBranchElement*)fBranch)->GetType()==3 ) {
393 
394  Int_t id = ((TBranchElement*)fBranch)->GetID();
395  if (id>=0) {
396 
397  fElement = ((TStreamerElement*)(((TBranchElement*)fBranch)->GetInfo())->GetElements()->At(id));
398  fClass = fElement->GetClassPointer();
399  if (fClass) fClassName = fClass->GetName();
400 
401  }
402  }
403  if (fClass==0 && fClassName.Length()) fClass = TClass::GetClass(fClassName);
404  */
405  //fprintf(stderr,"For %s fClass is %p which is %s\n",
406  // fBranchName.Data(),fClass,fClass==0?"not set":fClass->GetName());
407 
408  if ( fBranch->IsA()==TBranchElement::Class() &&
409  (((TBranchElement*)fBranch)->GetType()==3 || fClass==TClonesArray::Class()) &&
410  !fIsMember ) {
411  fIsClone = true;
412  }
413 
414  if (fIsMember) {
415  if ( fBranch->IsA()==TBranchElement::Class() &&
417  (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
418 
420  TString member;
421  if (bcount) {
422  TString bname = fBranch->GetName();
423  TString bcname = bcount->GetName();
424  member = bname.Remove(0,bcname.Length()+1);
425  } else {
426  member = fDataMember;
427  }
428 
430 
431  if (fMemberOffset<0) {
432  Error("Setup","%s",Form("Negative offset %d for %s in %s",
434  bcount?bcount->GetName():"unknown"));
435  }
436 
437  } else if (fClass) {
438 
441  if (fElement)
443  else {
444  // Need to compose the proper sub name
445 
446  TString member;
447 
448  member += fDataMember;
450 
451  }
452  // The extra condition (fElement is not a TStreamerSTL) is to handle the case where fBranch is a
453  // TBranchElement and fElement is a TStreamerSTL. Without the extra condition we get an error
454  // message, although the vector (i.e. the TBranchElement) is accessible.
455  } else if (fBranch->IsA() != TBranch::Class() && fElement->IsA() != TStreamerBasicType::Class()
456  && fElement->IsA() != TStreamerSTL::Class()) {
457  Error("Setup","%s",Form("Missing TClass object for %s\n",fClassName.Data()));
458  }
459 
460  if ( fBranch->IsA()==TBranchElement::Class()
461  && (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
462 
464 
465  } else {
466 
467  fWhere = ((unsigned char*)fWhere) + fMemberOffset;
468  }
469  }
470  }
471  if (fClass==TClonesArray::Class()) fIsClone = true;
472  if (fWhere!=0) {
474  fCurrentTreeNumber = fLastTree->GetTreeNumber();
475  fInitialized = true;
476  return true;
477  } else {
478  return false;
479  }
480 }
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
Definition: TBranch.cxx:1275
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2258
Int_t GetType() const
virtual TClass * GetValueClass() const =0
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
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:4420
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
#define R__ASSERT(e)
Definition: TError.h:96
TStreamerElement * fElement
Definition: TBranchProxy.h:84
Int_t GetOffset() const
Definition: TBranch.h:190
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2816
virtual void * GetStart(UInt_t=0)
Definition: TBranchProxy.h:222
Int_t GetArrayLength() const
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
TBranchElement * GetBranchCount() const
void Class()
Definition: Class.C:29
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:414
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1645
Int_t GetID() const
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 Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:310
char * GetObject() const
Return a pointer to our object.
char * Form(const char *fmt,...)
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:74
virtual void * GetValuePointer() const
Definition: TLeaf.h:88
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
Int_t GetElementOffset(Int_t id) const
A Branch for the case of an object.
#define ClassImp(name)
Definition: Rtypes.h:359
virtual TObjArray * GetElements() const =0
virtual Bool_t IsaPointer() const
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
Long_t GetDataMemberOffset(const char *membername) const
return offset for member name.
Definition: TClass.cxx:3308
TObjArray * GetListOfLeaves()
Definition: TBranch.h:202
Internal::TBranchProxyDirector * fDirector
Definition: TBranchProxy.h:68
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:2887
TClass * GetClass() const
Definition: TClonesArray.h:56
TObjArray * GetElements() const
An array of clone (identical) objects.
Definition: TClonesArray.h:32
static std::string GetFriendBranchName(TTree *directorTree, TBranch *branch, const char *fullBranchName)
For a fullBranchName that might contain a leading friend tree path (but access elements designating a...
TTree * GetTree() const
Definition: TBranch.h:207
virtual char * GetAddress() const
Definition: TBranch.h:169
Base class for all the proxy object.
Definition: TBranchProxy.h:66
TBranch * GetBranch() const
Definition: TLeaf.h:71
A TTree is a list of TBranches.
Definition: TBranch.h:62
Int_t GetOffset() const
TVirtualCollectionProxy * fCollection
Definition: TBranchProxy.h:99
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1718
char name[80]
Definition: TGX11.cxx:109
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
virtual TVirtualCollectionProxy * Generate() const =0
void Attach(Detail::TBranchProxy *p)