Logo ROOT   master
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 implementation
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  fNotify(this),
33  fRead(-1), fWhere(0),fCollection(0)
34 {
35  // Constructor.
36 };
37 
39  const char* name) :
40  fDirector(boss), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
41  fHasLeafCount(false), fBranchName(top), fParent(0), fDataMember(""),
42  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
43  fBranch(0), fBranchCount(0),
44  fNotify(this),
45  fRead(-1), fWhere(0),fCollection(0)
46 {
47  // Constructor.
48 
49  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.' && name) {
50  ((TString&)fBranchName).Append(".");
51  }
52  if (name) ((TString&)fBranchName).Append(name);
53  boss->Attach(this);
54 }
55 
56 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, const char *top, const char *name, const char *membername) :
57  fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
58  fHasLeafCount(false), fBranchName(top), fParent(0), fDataMember(membername),
59  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
60  fBranch(0), fBranchCount(0),
61  fNotify(this),
62  fRead(-1), fWhere(0),fCollection(0)
63 {
64  // Constructor.
65 
66  if (name && strlen(name)) {
67  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
68  ((TString&)fBranchName).Append(".");
69  }
70  ((TString&)fBranchName).Append(name);
71  }
72  boss->Attach(this);
73 }
74 
75 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, Detail::TBranchProxy *parent, const char* membername, const char* top,
76  const char* name) :
77  fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
78  fHasLeafCount(false), fBranchName(top), fParent(parent), fDataMember(membername),
79  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
80  fBranch(0), fBranchCount(0),
81  fNotify(this),
82  fRead(-1), fWhere(0),fCollection(0)
83 {
84  // Constructor.
85 
86  if (name && strlen(name)) {
87  if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
88  ((TString&)fBranchName).Append(".");
89  }
90  ((TString&)fBranchName).Append(name);
91  }
92  boss->Attach(this);
93 }
94 
96  fDirector(boss), fInitialized(false), fIsMember(membername != 0 && membername[0]), fIsClone(false), fIsaPointer(false),
97  fHasLeafCount(false), fBranchName(branch->GetName()), fParent(0), fDataMember(membername),
98  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
99  fBranch(0), fBranchCount(0),
100  fNotify(this),
101  fRead(-1), fWhere(0),fCollection(0)
102 {
103  // Constructor.
104 
105  boss->Attach(this);
106 }
107 
108 /// For a fullBranchName that might contain a leading friend tree path (but
109 /// access elements designating a leaf), but the leaf name such that it matches
110 /// the "path" to branch.
111 static std::string GetFriendBranchName(TTree* directorTree, TBranch* branch, const char* fullBranchName)
112 {
113  // ROOT-10046: Here we need to ask for the tree with GetTree otherwise, if directorTree
114  // is a chain, this check is bogus and a bug can occour (ROOT-10046)
115  if (directorTree->GetTree() == branch->GetTree())
116  return branch->GetName();
117 
118  // Friend case:
119  std::string sFullBranchName = fullBranchName;
120  std::string::size_type pos = sFullBranchName.rfind(branch->GetName());
121  if (pos != std::string::npos) {
122  sFullBranchName.erase(pos);
123  sFullBranchName += branch->GetName();
124  }
125  return sFullBranchName;
126 }
127 
128 /// Constructor taking the branch name, possibly of a friended tree.
129 /// Used by TTreeReaderValue in place of TFriendProxy.
130 ROOT::Detail::TBranchProxy::TBranchProxy(TBranchProxyDirector* boss, const char* branchname, TBranch* branch, const char* membername) :
131  fDirector(boss), fInitialized(false), fIsMember(membername != 0 && membername[0]), fIsClone(false), fIsaPointer(false),
132  fHasLeafCount(false), fBranchName(GetFriendBranchName(boss->GetTree(), branch, branchname)), fParent(0), fDataMember(membername),
133  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
134  fBranch(0), fBranchCount(0),
135  fNotify(this),
136  fRead(-1), fWhere(0),fCollection(0)
137 {
138  // Constructor.
139 
140  boss->Attach(this);
141 }
142 
144 {
145  // Typical Destructor
146  if (fNotify.IsLinked() && fDirector && fDirector->GetTree())
147  fNotify.RemoveLink(*(fDirector->GetTree()));
148 }
149 
151 {
152  // Completely reset the object.
153 
154  fWhere = 0;
155  fBranch = 0;
156  fBranchCount = 0;
157  fRead = -1;
158  fClass = 0;
159  fElement = 0;
160  fMemberOffset = 0;
161  fOffset = 0;
162  fArrayLength = 1;
163  fIsClone = false;
164  fInitialized = false;
165  fHasLeafCount = false;
166  delete fCollection;
167  fCollection = 0;
168 }
169 
171 {
172  // Display the content of the object
173 
174  std::cout << "fBranchName " << fBranchName << std::endl;
175  //std::cout << "fTree " << fDirector->fTree << std::endl;
176  std::cout << "fBranch " << fBranch << std::endl;
177  if (fBranchCount) std::cout << "fBranchCount " << fBranchCount << std::endl;
178 }
179 
181 {
182  // Initialize/cache the necessary information.
183 
184  // Should we check the type?
185 
186  if (!fDirector->GetTree()) {
187  return false;
188  }
189  if (!fNotify.IsLinked()) {
190  fNotify.PrependLink(*fDirector->GetTree());
191  }
192  if (fParent) {
193 
194  if (!fParent->Setup()) {
195  return false;
196  }
197 
198  TClass *pcl = fParent->GetClass();
199  R__ASSERT(pcl);
200 
201  if (pcl==TClonesArray::Class()) {
202  // We always skip the clones array
203 
204  Int_t i = fDirector->GetReadEntry();
205  if (i<0) fDirector->SetReadEntry(0);
206  if (fParent->Read()) {
207  if (i<0) fDirector->SetReadEntry(i);
208 
209  TClonesArray *clones;
210  clones = (TClonesArray*)fParent->GetStart();
211 
212  if (clones) pcl = clones->GetClass();
213  }
214  } else if (pcl->GetCollectionProxy()) {
215  // We always skip the collections.
216 
217  if (fCollection) delete fCollection;
218  fCollection = pcl->GetCollectionProxy()->Generate();
219  pcl = fCollection->GetValueClass();
220  if (pcl == 0) {
221  // coverity[dereference] fparent is checked jus a bit earlier and can not be null here
222  Error("Setup","Not finding TClass for collecion for the data member %s seems no longer be in class %s",fDataMember.Data(),fParent->GetClass()->GetName());
223  return false;
224  }
225  }
226 
227  fElement = (TStreamerElement*)pcl->GetStreamerInfo()->GetStreamerElement(fDataMember, fOffset);
228  if (fElement) {
229  fIsaPointer = fElement->IsaPointer();
230  fClass = fElement->GetClassPointer();
231  fMemberOffset = fElement->GetOffset();
232  fArrayLength = fElement->GetArrayLength();
233  } else {
234  Error("Setup","Data member %s seems no longer be in class %s",fDataMember.Data(),pcl->GetName());
235  return false;
236  }
237 
238  fIsClone = (fClass==TClonesArray::Class());
239 
240  fWhere = fParent->fWhere; // not really used ... it is reset by GetStart and GetClStart
241 
242  if (fParent->IsaPointer()) {
243  // fprintf(stderr,"non-split pointer de-referencing non implemented yet \n");
244  // nothing to do!
245  } else {
246  // Accumulate offsets.
247  // or not!? fOffset = fMemberOffset = fMemberOffset + fParent->fOffset;
248  }
249 
250  // This is not sufficient for following pointers
251 
252  } else {
253 
254  // This does not allow (yet) to precede the branch name with
255  // its mother's name
256  fBranch = fDirector->GetTree()->GetBranch(fBranchName.Data());
257  if (!fBranch) {
258  // FIXME
259  // While fixing ROOT-10019, this error was added to give to the user an even better experience
260  // in presence of a problem.
261  // It is not easy to distinguish the cases where this error is "expected"
262  // For now we do not print anything - see conversation here: https://github.com/root-project/root/pull/3746
263  //auto treeName = fDirector->GetTree()->GetName();
264  //::Error("TBranchProxy::Setup", "%s", Form("Unable to find branch %s in tree %s.\n",fBranchName.Data(), treeName));
265  return false;
266  }
267 
268  {
269  // Calculate fBranchCount for a leaf.
270  TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
271  if (leaf) leaf = leaf->GetLeafCount();
272  if (leaf) {
273  fBranchCount = leaf->GetBranch();
274  // fprintf(stderr,"for leaf %s setting up leafcount %s branchcount %s\n",
275  // fBranch->GetName(),leaf->GetName(),fBranchCount->GetName());
276  //fBranchCount->Print();
277  }
278  }
279 
280  fWhere = (double*)fBranch->GetAddress();
281 
282  if (!fWhere && fBranch->IsA()==TBranchElement::Class()
283  && ((TBranchElement*)fBranch)->GetMother()) {
284 
285  TBranchElement* be = ((TBranchElement*)fBranch);
286 
287  be->GetMother()->SetAddress(0);
288  fWhere = (double*)fBranch->GetAddress();
289 
290  }
291  if (fBranch->IsA()==TBranch::Class()) {
292  TLeaf *leaf2 = nullptr;
293  if (fDataMember.Length()) {
294  leaf2 = fBranch->GetLeaf(fDataMember);
295  } else if (!fWhere) {
296  leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
297  fWhere = leaf2->GetValuePointer();
298  }
299  if (leaf2) {
300  fWhere = leaf2->GetValuePointer();
301  fArrayLength = leaf2->GetLen();
302  if (leaf2->GetLeafCount()) {
303  fLeafCount = leaf2->GetLeafCount();
304  fHasLeafCount = true;
305  }
306  }
307  }
308 
309  if (!fWhere) {
310  fBranch->SetAddress(0);
311  fWhere = (double*)fBranch->GetAddress();
312  }
313 
314 
315  if (fWhere && fBranch->IsA()==TBranchElement::Class()) {
316 
317  TBranchElement* be = ((TBranchElement*)fBranch);
318 
319  TStreamerInfo * info = be->GetInfo();
320  Int_t id = be->GetID();
321  if (be->GetType() == 3) {
322  fClassName = "TClonesArray";
324  } else if (id>=0) {
325  fOffset = info->GetElementOffset(id);
326  fElement = (TStreamerElement*)info->GetElements()->At(id);
327  fIsaPointer = fElement->IsaPointer();
328  fClass = fElement->GetClassPointer();
329 
330  if ((fIsMember || (be->GetType()!=3 && be->GetType() !=4))
331  && (be->GetType()!=31 && be->GetType()!=41)) {
332 
333  if (fClass==TClonesArray::Class()) {
334  Int_t i = be->GetTree()->GetReadEntry();
335  if (i<0) i = 0;
336  be->GetEntry(i);
337 
338  TClonesArray *clones;
339  if ( fIsMember && be->GetType()==3 ) {
340  clones = (TClonesArray*)be->GetObject();
341  } else if (fIsaPointer) {
342  clones = (TClonesArray*)*(void**)((char*)fWhere+fOffset);
343  } else {
344  clones = (TClonesArray*)((char*)fWhere+fOffset);
345  }
346  if (!fIsMember) fIsClone = true;
347  fClass = clones->GetClass();
348  } else if (fClass && fClass->GetCollectionProxy()) {
349  delete fCollection;
350  fCollection = fClass->GetCollectionProxy()->Generate();
351  fClass = fCollection->GetValueClass();
352  }
353 
354  }
355  if (fClass) fClassName = fClass->GetName();
356  } else {
357  fClassName = be->GetClassName();
358  fClass = TClass::GetClass(fClassName);
359  }
360 
361  if (be->GetType()==3) {
362  // top level TClonesArray
363 
364  if (!fIsMember) fIsClone = true;
365  fIsaPointer = false;
366  fWhere = be->GetObject();
367 
368  } else if (be->GetType()==4) {
369  // top level TClonesArray
370 
371  fCollection = be->GetCollectionProxy()->Generate();
372  fIsaPointer = false;
373  fWhere = be->GetObject();
374 
375  } else if (id<0) {
376  // top level object
377 
378  fIsaPointer = false;
379  fWhere = be->GetObject();
380 
381  } else if (be->GetType()==41) {
382 
383  fCollection = be->GetCollectionProxy()->Generate();
384  fWhere = be->GetObject();
385  fOffset += be->GetOffset();
386 
387  } else if (be->GetType()==31) {
388 
389  fWhere = be->GetObject();
390  fOffset += be->GetOffset();
391 
392  } else if (be->GetType()==2) {
393  // this might also be the right path for GetType()==1
394 
395  fWhere = be->GetObject();
396 
397  } else {
398 
399  // fWhere = ((unsigned char*)fWhere) + fOffset;
400  fWhere = ((unsigned char*)be->GetObject()) + fOffset;
401 
402  }
403  } else {
404  fClassName = fBranch->GetClassName();
405  fClass = TClass::GetClass(fClassName);
406  }
407 
408 
409  /*
410  fClassName = fBranch->GetClassName(); // What about TClonesArray?
411  if ( fBranch->IsA()==TBranchElement::Class() &&
412  ((TBranchElement*)fBranch)->GetType()==31 ||((TBranchElement*)fBranch)->GetType()==3 ) {
413 
414  Int_t id = ((TBranchElement*)fBranch)->GetID();
415  if (id>=0) {
416 
417  fElement = ((TStreamerElement*)(((TBranchElement*)fBranch)->GetInfo())->GetElements()->At(id));
418  fClass = fElement->GetClassPointer();
419  if (fClass) fClassName = fClass->GetName();
420 
421  }
422  }
423  if (fClass==0 && fClassName.Length()) fClass = TClass::GetClass(fClassName);
424  */
425  //fprintf(stderr,"For %s fClass is %p which is %s\n",
426  // fBranchName.Data(),fClass,fClass==0?"not set":fClass->GetName());
427 
428  if ( fBranch->IsA()==TBranchElement::Class() &&
429  (((TBranchElement*)fBranch)->GetType()==3 || fClass==TClonesArray::Class()) &&
430  !fIsMember ) {
431  fIsClone = true;
432  }
433 
434  if (fIsMember) {
435  if ( fBranch->IsA()==TBranchElement::Class() &&
437  (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
438 
439  TBranchElement *bcount = ((TBranchElement*)fBranch)->GetBranchCount();
440  TString member;
441  if (bcount) {
442  TString bname = fBranch->GetName();
443  TString bcname = bcount->GetName();
444  member = bname.Remove(0,bcname.Length()+1);
445  } else {
446  member = fDataMember;
447  }
448 
449  fMemberOffset = fClass->GetDataMemberOffset(member);
450 
451  if (fMemberOffset<0) {
452  Error("Setup","%s",Form("Negative offset %d for %s in %s",
453  fMemberOffset,fBranch->GetName(),
454  bcount?bcount->GetName():"unknown"));
455  }
456 
457  } else if (fClass) {
458 
459  fElement = (TStreamerElement*)
460  fClass->GetStreamerInfo()->GetElements()->FindObject(fDataMember);
461  if (fElement)
462  fMemberOffset = fElement->GetOffset();
463  else {
464  // Need to compose the proper sub name
465 
466  TString member;
467 
468  member += fDataMember;
469  fMemberOffset = fClass->GetDataMemberOffset(member);
470 
471  }
472  // The extra condition (fElement is not a TStreamerSTL) is to handle the case where fBranch is a
473  // TBranchElement and fElement is a TStreamerSTL. Without the extra condition we get an error
474  // message, although the vector (i.e. the TBranchElement) is accessible.
475  } else if (fBranch->IsA() != TBranch::Class() && fElement->IsA() != TStreamerBasicType::Class()
476  && fElement->IsA() != TStreamerSTL::Class()) {
477  Error("Setup","%s",Form("Missing TClass object for %s\n",fClassName.Data()));
478  }
479 
480  if ( fBranch->IsA()==TBranchElement::Class()
481  && (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
482 
483  fOffset = fMemberOffset;
484 
485  } else {
486 
487  fWhere = ((unsigned char*)fWhere) + fMemberOffset;
488  }
489  }
490  }
491  if (fClass==TClonesArray::Class()) fIsClone = true;
492  if (fWhere!=0) {
493  fInitialized = true;
494  return true;
495  } else {
496  return false;
497  }
498 }
Describe Streamer information for one class version
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:55
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:2496
Int_t GetType() const
Cppyy::TCppType_t fClass
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:4502
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
#define R__ASSERT(e)
Definition: TError.h:96
Int_t GetOffset() const
Definition: TBranch.h:226
Basic string class.
Definition: TString.h:131
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2852
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
TBranchElement * GetBranchCount() const
void Class()
Definition: Class.C:29
virtual Long64_t GetReadEntry() const
Definition: TTree.h:500
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 void SetAddress(void *add=0)
Definition: TLeaf.h:181
void Error(const char *location, const char *msgfmt,...)
virtual TTree * GetTree() const
Definition: TTree.h:508
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:368
virtual TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const =0
char * GetObject() const
Return a pointer to our object.
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:405
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:117
virtual void * GetValuePointer() const
Definition: TLeaf.h:134
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
Int_t GetElementOffset(Int_t id) const
A Branch for the case of an object.
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
#define ClassImp(name)
Definition: Rtypes.h:361
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. ...
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:2923
TClass * GetClass() const
Definition: TClonesArray.h:53
TObjArray * GetElements() const
An array of clone (identical) objects.
Definition: TClonesArray.h:29
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:243
virtual char * GetAddress() const
Definition: TBranch.h:204
A TTree represents a columnar dataset.
Definition: TTree.h:78
Base class for all the proxy object.
Definition: TBranchProxy.h:68
TBranch * GetBranch() const
Definition: TLeaf.h:113
A TTree is a list of TBranches.
Definition: TBranch.h:88
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1956
char name[80]
Definition: TGX11.cxx:109
virtual TVirtualCollectionProxy * Generate() const =0
void Attach(Detail::TBranchProxy *p)