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