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