Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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(nullptr), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
33 fHasLeafCount(false), fBranchName(""), fParent(nullptr), fDataMember(""),
34 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
35 fBranch(nullptr), fBranchCount(nullptr),
36 fNotify(this),
37 fRead(-1), fWhere(nullptr),fCollection(nullptr)
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(nullptr), fDataMember(""),
48 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
49 fBranch(nullptr), fBranchCount(nullptr),
50 fNotify(this),
51 fRead(-1), fWhere(nullptr),fCollection(nullptr)
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(nullptr), fDataMember(membername),
66 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
67 fBranch(nullptr), fBranchCount(nullptr),
68 fNotify(this),
69 fRead(-1), fWhere(nullptr),fCollection(nullptr)
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(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
88 fBranch(nullptr), fBranchCount(nullptr),
89 fNotify(this),
90 fRead(-1), fWhere(nullptr),fCollection(nullptr)
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 != nullptr && membername[0]), fIsClone(false), fIsaPointer(false),
106 fHasLeafCount(false), fBranchName(branch->GetName()), fParent(nullptr), fDataMember(membername),
107 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
108 fBranch(nullptr), fBranchCount(nullptr),
109 fNotify(this),
110 fRead(-1), fWhere(nullptr),fCollection(nullptr)
111{
112 boss->Attach(this);
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 != nullptr && membername[0]), fIsClone(false), fIsaPointer(false),
143 fHasLeafCount(false), fBranchName(GetFriendBranchName(boss->GetTree(), branch, branchname)), fParent(nullptr), fDataMember(membername),
144 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
145 fBranch(nullptr), fBranchCount(nullptr),
146 fNotify(this),
147 fRead(-1), fWhere(nullptr),fCollection(nullptr)
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 = nullptr;
169 fBranch = nullptr;
170 fBranchCount = nullptr;
171 fRead = -1;
172 fClass = nullptr;
173 fElement = nullptr;
174 fMemberOffset = 0;
175 fOffset = 0;
176 fArrayLength = 1;
177 fIsClone = false;
178 fInitialized = false;
179 fHasLeafCount = false;
180 delete fCollection;
181 fCollection = nullptr;
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 (fHasLeafCount)
193 std::cout << "fLeafCount " << fLeafCount << std::endl;
194 else if (fBranchCount)
195 std::cout << "fBranchCount " << fBranchCount << std::endl;
196}
197
198
199////////////////////////////////////////////////////////////////////////////////
200/// Initialize/cache the necessary information.
201
203{
204 // Should we check the type?
205
206 if (!fDirector->GetTree()) {
207 return false;
208 }
209 if (!fNotify.IsLinked()) {
210 fNotify.PrependLink(*fDirector->GetTree());
211 }
212 if (fParent) {
213
214 if (!fParent->Setup()) {
215 return false;
216 }
217
218 TClass *pcl = fParent->GetClass();
219 R__ASSERT(pcl);
220
221 if (pcl==TClonesArray::Class()) {
222 // We always skip the clones array
223
224 Int_t i = fDirector->GetReadEntry();
225 if (i<0) fDirector->SetReadEntry(0);
226 if (fParent->Read()) {
227 if (i<0) fDirector->SetReadEntry(i);
228
229 TClonesArray *clones;
230 clones = (TClonesArray*)fParent->GetStart();
231
232 if (clones) pcl = clones->GetClass();
233 }
234 } else if (pcl->GetCollectionProxy()) {
235 // We always skip the collections.
236
237 if (fCollection) delete fCollection;
238 fCollection = pcl->GetCollectionProxy()->Generate();
239 pcl = fCollection->GetValueClass();
240 if (pcl == nullptr) {
241 // coverity[dereference] fparent is checked jus a bit earlier and can not be null here
242 Error("Setup","Not finding TClass for collection for the data member %s seems no longer be in class %s",fDataMember.Data(),fParent->GetClass()->GetName());
243 return false;
244 }
245 }
246
247 fElement = (TStreamerElement*)pcl->GetStreamerInfo()->GetStreamerElement(fDataMember, fOffset);
248 if (fElement) {
249 fIsaPointer = fElement->IsaPointer();
250 fClass = fElement->GetClassPointer();
251 fMemberOffset = fElement->GetOffset();
252 fArrayLength = fElement->GetArrayLength();
253 } else {
254 Error("Setup","Data member %s seems no longer be in class %s",fDataMember.Data(),pcl->GetName());
255 return false;
256 }
257
258 fIsClone = (fClass==TClonesArray::Class());
259
260 fWhere = fParent->fWhere; // not really used ... it is reset by GetStart and GetClStart
261
262 if (fParent->IsaPointer()) {
263 // fprintf(stderr,"non-split pointer de-referencing non implemented yet \n");
264 // nothing to do!
265 } else {
266 // Accumulate offsets.
267 // or not!? fOffset = fMemberOffset = fMemberOffset + fParent->fOffset;
268 }
269
270 // This is not sufficient for following pointers
271
272 } else {
273
274 // This does not allow (yet) to precede the branch name with
275 // its mother's name
276 fBranch = fDirector->GetTree()->GetBranch(fBranchName.Data());
277 if (!fBranch) {
278 // FIXME
279 // While fixing ROOT-10019, this error was added to give to the user an even better experience
280 // in presence of a problem.
281 // It is not easy to distinguish the cases where this error is "expected"
282 // For now we do not print anything - see conversation here: https://github.com/root-project/root/pull/3746
283 //auto treeName = fDirector->GetTree()->GetName();
284 //::Error("TBranchProxy::Setup", "%s", Form("Unable to find branch %s in tree %s.\n",fBranchName.Data(), treeName));
285 return false;
286 }
287
288 fWhere = (double*)fBranch->GetAddress();
289
290 if (!fWhere && fBranch->IsA()==TBranchElement::Class()
291 && ((TBranchElement*)fBranch)->GetMother()) {
292
293 TBranchElement* be = ((TBranchElement*)fBranch);
294
295 be->GetMother()->SetAddress(nullptr);
296 fWhere = (double*)fBranch->GetAddress();
297
298 }
299 if (fBranch->IsA()==TBranch::Class()) {
300 TLeaf *leaf2 = nullptr;
301 if (fDataMember.Length()) {
302 leaf2 = fBranch->GetLeaf(fDataMember);
303 } else if (!fWhere) {
304 leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
305 fWhere = leaf2->GetValuePointer();
306 }
307 if (leaf2) {
308 fWhere = leaf2->GetValuePointer();
309 fArrayLength = leaf2->GetLen();
310 if (leaf2->GetLeafCount()) {
311 fLeafCount = leaf2->GetLeafCount();
312 fHasLeafCount = true;
313 }
314 }
315 } else if (fBranch->IsA() == TBranchElement::Class()) {
316 // Calculate fBranchCount for a leaf.
317 TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
318 if (leaf)
319 leaf = leaf->GetLeafCount();
320 if (leaf) {
321 fBranchCount = dynamic_cast<TBranchElement*>(leaf->GetBranch());
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!=nullptr) {
512 fInitialized = true;
513 return true;
514 } else {
515 return false;
516 }
517}
Cppyy::TCppType_t fClass
#define ClassImp(name)
Definition Rtypes.h:377
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:185
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
Base class for all the proxy object.
bool 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
static TClass * Class()
Int_t GetID() const
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
void SetupAddresses() override
If the branch address is not set, we set all addresses starting with the top level parent branch.
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
Int_t GetEntry(Long64_t entry=0, Int_t getall=0) override
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
TClass * IsA() const override
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
TTree * GetTree() const
Definition TBranch.h:252
static TClass * Class()
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:2031
virtual void SetAddress(void *add)
Set address of this branch.
Definition TBranch.cxx:2682
Int_t GetOffset() const
Definition TBranch.h:235
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
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:4599
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2897
TClass * IsA() const override
Definition TClass.h:618
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:2968
An array of clone (identical) objects.
TClass * GetClass() const
static TClass * Class()
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
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
static TClass * Class()
virtual Bool_t IsaPointer() const
Describes a persistent version of a class.
Int_t GetElementOffset(Int_t id) const override
TObjArray * GetElements() const override
static TClass * Class()
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
const char * Data() const
Definition TString.h:376
TString & Remove(Ssiz_t pos)
Definition TString.h:685
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Long64_t GetReadEntry() const
Definition TTree.h:509
virtual TTree * GetTree() const
Definition TTree.h:517
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual TVirtualCollectionProxy * Generate() const =0
Returns a clean object of the actual class that derives from TVirtualCollectionProxy.
virtual TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const =0