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