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