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