Logo ROOT   6.12/06
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(""),
41  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
42  fBranch(0), fBranchCount(0),
43  fLastTree(0), fRead(-1), fWhere(0),fCollection(0), fCurrentTreeNumber(-1)
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),
57  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
58  fBranch(0), fBranchCount(0),
59  fLastTree(0), fRead(-1), fWhere(0),fCollection(0), fCurrentTreeNumber(-1)
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),
76  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
77  fBranch(0), fBranchCount(0),
78  fLastTree(0), fRead(-1), fWhere(0),fCollection(0), fCurrentTreeNumber(-1)
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),
94  fClassName(""), fClass(0), fElement(0), fMemberOffset(0), fOffset(0), fArrayLength(1),
95  fBranch(0), fBranchCount(0),
96  fLastTree(0), fRead(-1), fWhere(0),fCollection(0), fCurrentTreeNumber(-1)
97 {
98  // Constructor.
99 
100  boss->Attach(this);
101 }
102 
104 {
105  // Typical Destructor
106 }
107 
109 {
110  // Completely reset the object.
111 
112  fWhere = 0;
113  fBranch = 0;
114  fBranchCount = 0;
115  fRead = -1;
116  fClass = 0;
117  fElement = 0;
118  fMemberOffset = 0;
119  fOffset = 0;
120  fArrayLength = 1;
121  fIsClone = false;
122  fInitialized = false;
123  fHasLeafCount = false;
124  fLastTree = 0;
125  delete fCollection;
126  fCollection = 0;
127  fCurrentTreeNumber = -1;
128 }
129 
131 {
132  // Display the content of the object
133 
134  std::cout << "fBranchName " << fBranchName << std::endl;
135  //std::cout << "fTree " << fDirector->fTree << std::endl;
136  std::cout << "fBranch " << fBranch << std::endl;
137  if (fBranchCount) std::cout << "fBranchCount " << fBranchCount << std::endl;
138 }
139 
141 {
142  // Initialize/cache the necessary information.
143 
144  // Should we check the type?
145 
146  if (!fDirector->GetTree()) {
147  return false;
148  }
149  if (fParent) {
150 
151  if (!fParent->Setup()) {
152  return false;
153  }
154 
155  TClass *pcl = fParent->GetClass();
156  R__ASSERT(pcl);
157 
158  if (pcl==TClonesArray::Class()) {
159  // We always skip the clones array
160 
161  Int_t i = fDirector->GetReadEntry();
162  if (i<0) fDirector->SetReadEntry(0);
163  if (fParent->Read()) {
164  if (i<0) fDirector->SetReadEntry(i);
165 
166  TClonesArray *clones;
167  clones = (TClonesArray*)fParent->GetStart();
168 
169  if (clones) pcl = clones->GetClass();
170  }
171  } else if (pcl->GetCollectionProxy()) {
172  // We always skip the collections.
173 
174  if (fCollection) delete fCollection;
175  fCollection = pcl->GetCollectionProxy()->Generate();
176  pcl = fCollection->GetValueClass();
177  if (pcl == 0) {
178  // coverity[dereference] fparent is checked jus a bit earlier and can not be null here
179  Error("Setup","Not finding TClass for collecion for the data member %s seems no longer be in class %s",fDataMember.Data(),fParent->GetClass()->GetName());
180  return false;
181  }
182  }
183 
184  fElement = (TStreamerElement*)pcl->GetStreamerInfo()->GetElements()->FindObject(fDataMember);
185  if (fElement == 0) {
186  Error("Setup","Data member %s seems no longer be in class %s",fDataMember.Data(),pcl->GetName());
187  return false;
188  }
189 
190  fIsaPointer = fElement->IsaPointer();
191  fClass = fElement->GetClassPointer();
192 
193 
194  fIsClone = (fClass==TClonesArray::Class());
195 
196  fOffset = fMemberOffset = fElement->GetOffset();
197 
198  fArrayLength = fElement->GetArrayLength();
199 
200  fWhere = fParent->fWhere; // not really used ... it is reset by GetStart and GetClStart
201 
202  if (fParent->IsaPointer()) {
203  // fprintf(stderr,"non-split pointer de-referencing non implemented yet \n");
204  // nothing to do!
205  } else {
206  // Accumulate offsets.
207  // or not!? fOffset = fMemberOffset = fMemberOffset + fParent->fOffset;
208  }
209 
210  // This is not sufficient for following pointers
211 
212  } else if (!fBranch || fCurrentTreeNumber != fDirector->GetTree()->GetTreeNumber() || fLastTree != fDirector->GetTree()) {
213 
214  // This does not allow (yet) to precede the branch name with
215  // its mother's name
216  fBranch = fDirector->GetTree()->GetBranch(fBranchName.Data());
217  if (!fBranch) return false;
218 
219  {
220  // Calculate fBranchCount for a leaf.
221  TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
222  if (leaf) leaf = leaf->GetLeafCount();
223  if (leaf) {
224  fBranchCount = leaf->GetBranch();
225  // fprintf(stderr,"for leaf %s setting up leafcount %s branchcount %s\n",
226  // fBranch->GetName(),leaf->GetName(),fBranchCount->GetName());
227  //fBranchCount->Print();
228  }
229  }
230 
231  fWhere = (double*)fBranch->GetAddress();
232 
233  if (!fWhere && fBranch->IsA()==TBranchElement::Class()
234  && ((TBranchElement*)fBranch)->GetMother()) {
235 
236  TBranchElement* be = ((TBranchElement*)fBranch);
237 
238  be->GetMother()->SetAddress(0);
239  fWhere = (double*)fBranch->GetAddress();
240 
241  }
242  if (fBranch->IsA()==TBranch::Class()) {
243  TLeaf *leaf2 = nullptr;
244  if (fDataMember.Length()) {
245  leaf2 = fBranch->GetLeaf(fDataMember);
246  } else if (!fWhere) {
247  leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
248  fWhere = leaf2->GetValuePointer();
249  }
250  if (leaf2) {
251  fWhere = leaf2->GetValuePointer();
252  fArrayLength = leaf2->GetLen();
253  if (leaf2->GetLeafCount()) {
254  fLeafCount = leaf2->GetLeafCount();
255  fHasLeafCount = true;
256  }
257  }
258  }
259 
260  if (!fWhere) {
261  fBranch->SetAddress(0);
262  fWhere = (double*)fBranch->GetAddress();
263  }
264 
265 
266  if (fWhere && fBranch->IsA()==TBranchElement::Class()) {
267 
268  TBranchElement* be = ((TBranchElement*)fBranch);
269 
270  TStreamerInfo * info = be->GetInfo();
271  Int_t id = be->GetID();
272  if (id>=0) {
273  fOffset = info->GetElementOffset(id);
274  fElement = (TStreamerElement*)info->GetElements()->At(id);
275  fIsaPointer = fElement->IsaPointer();
276  fClass = fElement->GetClassPointer();
277 
278  if ((fIsMember || (be->GetType()!=3 && be->GetType() !=4))
279  && (be->GetType()!=31 && be->GetType()!=41)) {
280 
281  if (fClass==TClonesArray::Class()) {
282  Int_t i = be->GetTree()->GetReadEntry();
283  if (i<0) i = 0;
284  be->GetEntry(i);
285 
286  TClonesArray *clones;
287  if ( fIsMember && be->GetType()==3 ) {
288  clones = (TClonesArray*)be->GetObject();
289  } else if (fIsaPointer) {
290  clones = (TClonesArray*)*(void**)((char*)fWhere+fOffset);
291  } else {
292  clones = (TClonesArray*)((char*)fWhere+fOffset);
293  }
294  if (!fIsMember) fIsClone = true;
295  fClass = clones->GetClass();
296  } else if (fClass && fClass->GetCollectionProxy()) {
297  delete fCollection;
298  fCollection = fClass->GetCollectionProxy()->Generate();
299  fClass = fCollection->GetValueClass();
300  }
301 
302  }
303  if (fClass) fClassName = fClass->GetName();
304  } else {
305  fClassName = be->GetClassName();
306  fClass = TClass::GetClass(fClassName);
307  }
308 
309  if (be->GetType()==3) {
310  // top level TClonesArray
311 
312  if (!fIsMember) fIsClone = true;
313  fIsaPointer = false;
314  fWhere = be->GetObject();
315 
316  } else if (be->GetType()==4) {
317  // top level TClonesArray
318 
319  fCollection = be->GetCollectionProxy()->Generate();
320  fIsaPointer = false;
321  fWhere = be->GetObject();
322 
323  } else if (id<0) {
324  // top level object
325 
326  fIsaPointer = false;
327  fWhere = be->GetObject();
328 
329  } else if (be->GetType()==41) {
330 
331  fCollection = be->GetCollectionProxy()->Generate();
332  fWhere = be->GetObject();
333  fOffset += be->GetOffset();
334 
335  } else if (be->GetType()==31) {
336 
337  fWhere = be->GetObject();
338  fOffset += be->GetOffset();
339 
340  } else if (be->GetType()==2) {
341  // this might also be the right path for GetType()==1
342 
343  fWhere = be->GetObject();
344 
345  } else {
346 
347  // fWhere = ((unsigned char*)fWhere) + fOffset;
348  fWhere = ((unsigned char*)be->GetObject()) + fOffset;
349 
350  }
351  } else {
352  fClassName = fBranch->GetClassName();
353  fClass = TClass::GetClass(fClassName);
354  }
355 
356 
357  /*
358  fClassName = fBranch->GetClassName(); // What about TClonesArray?
359  if ( fBranch->IsA()==TBranchElement::Class() &&
360  ((TBranchElement*)fBranch)->GetType()==31 ||((TBranchElement*)fBranch)->GetType()==3 ) {
361 
362  Int_t id = ((TBranchElement*)fBranch)->GetID();
363  if (id>=0) {
364 
365  fElement = ((TStreamerElement*)(((TBranchElement*)fBranch)->GetInfo())->GetElements()->At(id));
366  fClass = fElement->GetClassPointer();
367  if (fClass) fClassName = fClass->GetName();
368 
369  }
370  }
371  if (fClass==0 && fClassName.Length()) fClass = TClass::GetClass(fClassName);
372  */
373  //fprintf(stderr,"For %s fClass is %p which is %s\n",
374  // fBranchName.Data(),fClass,fClass==0?"not set":fClass->GetName());
375 
376  if ( fBranch->IsA()==TBranchElement::Class() &&
377  (((TBranchElement*)fBranch)->GetType()==3 || fClass==TClonesArray::Class()) &&
378  !fIsMember ) {
379  fIsClone = true;
380  }
381 
382  if (fIsMember) {
383  if ( fBranch->IsA()==TBranchElement::Class() &&
384  fClass==TClonesArray::Class() &&
385  (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
386 
387  TBranchElement *bcount = ((TBranchElement*)fBranch)->GetBranchCount();
388  TString member;
389  if (bcount) {
390  TString bname = fBranch->GetName();
391  TString bcname = bcount->GetName();
392  member = bname.Remove(0,bcname.Length()+1);
393  } else {
394  member = fDataMember;
395  }
396 
397  fMemberOffset = fClass->GetDataMemberOffset(member);
398 
399  if (fMemberOffset<0) {
400  Error("Setup","%s",Form("Negative offset %d for %s in %s",
401  fMemberOffset,fBranch->GetName(),
402  bcount?bcount->GetName():"unknown"));
403  }
404 
405  } else if (fClass) {
406 
407  fElement = (TStreamerElement*)
408  fClass->GetStreamerInfo()->GetElements()->FindObject(fDataMember);
409  if (fElement)
410  fMemberOffset = fElement->GetOffset();
411  else {
412  // Need to compose the proper sub name
413 
414  TString member;
415 
416  member += fDataMember;
417  fMemberOffset = fClass->GetDataMemberOffset(member);
418 
419  }
420  // The extra condition (fElement is not a TStreamerSTL) is to handle the case where fBranch is a
421  // TBranchElement and fElement is a TStreamerSTL. Without the extra condition we get an error
422  // message, although the vector (i.e. the TBranchElement) is accessible.
423  } else if (fBranch->IsA() != TBranch::Class() && fElement->IsA() != TStreamerBasicType::Class()
424  && fElement->IsA() != TStreamerSTL::Class()) {
425  Error("Setup","%s",Form("Missing TClass object for %s\n",fClassName.Data()));
426  }
427 
428  if ( fBranch->IsA()==TBranchElement::Class()
429  && (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
430 
431  fOffset = fMemberOffset;
432 
433  } else {
434 
435  fWhere = ((unsigned char*)fWhere) + fMemberOffset;
436  }
437  }
438  }
439  if (fClass==TClonesArray::Class()) fIsClone = true;
440  if (fWhere!=0) {
441  fLastTree = fDirector->GetTree();
442  fCurrentTreeNumber = fLastTree->GetTreeNumber();
443  fInitialized = true;
444  return true;
445  } else {
446  return false;
447  }
448 }
Describe Streamer information for one class version
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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:2170
Int_t GetType() const
virtual TClass * GetValueClass() const =0
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:4411
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:182
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2816
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
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:125
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:307
char * GetObject() const
Return a pointer to our object.
char * Form(const char *fmt,...)
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:72
virtual void * GetValuePointer() const
Definition: TLeaf.h:81
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 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:2887
TClass * GetClass() const
Definition: TClonesArray.h:56
TObjArray * GetElements() const
An array of clone (identical) objects.
Definition: TClonesArray.h:32
TTree * GetTree() const
Definition: TBranch.h:199
virtual char * GetAddress() const
Definition: TBranch.h:161
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:59
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1652
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)