Logo ROOT   6.16/01
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 if (directorTree == branch->GetTree())
116 return branch->GetName();
117
118 // Friend case:
119 std::string sFullBranchName = fullBranchName;
120 std::string::size_type pos = sFullBranchName.rfind(branch->GetName());
121 if (pos != std::string::npos) {
122 sFullBranchName.erase(pos);
123 sFullBranchName += branch->GetName();
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) return false;
258
259 {
260 // Calculate fBranchCount for a leaf.
261 TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
262 if (leaf) leaf = leaf->GetLeafCount();
263 if (leaf) {
264 fBranchCount = leaf->GetBranch();
265 // fprintf(stderr,"for leaf %s setting up leafcount %s branchcount %s\n",
266 // fBranch->GetName(),leaf->GetName(),fBranchCount->GetName());
267 //fBranchCount->Print();
268 }
269 }
270
271 fWhere = (double*)fBranch->GetAddress();
272
273 if (!fWhere && fBranch->IsA()==TBranchElement::Class()
274 && ((TBranchElement*)fBranch)->GetMother()) {
275
276 TBranchElement* be = ((TBranchElement*)fBranch);
277
278 be->GetMother()->SetAddress(0);
279 fWhere = (double*)fBranch->GetAddress();
280
281 }
282 if (fBranch->IsA()==TBranch::Class()) {
283 TLeaf *leaf2 = nullptr;
284 if (fDataMember.Length()) {
285 leaf2 = fBranch->GetLeaf(fDataMember);
286 } else if (!fWhere) {
287 leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
288 fWhere = leaf2->GetValuePointer();
289 }
290 if (leaf2) {
291 fWhere = leaf2->GetValuePointer();
292 fArrayLength = leaf2->GetLen();
293 if (leaf2->GetLeafCount()) {
294 fLeafCount = leaf2->GetLeafCount();
295 fHasLeafCount = true;
296 }
297 }
298 }
299
300 if (!fWhere) {
301 fBranch->SetAddress(0);
302 fWhere = (double*)fBranch->GetAddress();
303 }
304
305
306 if (fWhere && fBranch->IsA()==TBranchElement::Class()) {
307
308 TBranchElement* be = ((TBranchElement*)fBranch);
309
310 TStreamerInfo * info = be->GetInfo();
311 Int_t id = be->GetID();
312 if (be->GetType() == 3) {
313 fClassName = "TClonesArray";
314 fClass = TClonesArray::Class();
315 } else if (id>=0) {
316 fOffset = info->GetElementOffset(id);
317 fElement = (TStreamerElement*)info->GetElements()->At(id);
318 fIsaPointer = fElement->IsaPointer();
319 fClass = fElement->GetClassPointer();
320
321 if ((fIsMember || (be->GetType()!=3 && be->GetType() !=4))
322 && (be->GetType()!=31 && be->GetType()!=41)) {
323
324 if (fClass==TClonesArray::Class()) {
325 Int_t i = be->GetTree()->GetReadEntry();
326 if (i<0) i = 0;
327 be->GetEntry(i);
328
329 TClonesArray *clones;
330 if ( fIsMember && be->GetType()==3 ) {
331 clones = (TClonesArray*)be->GetObject();
332 } else if (fIsaPointer) {
333 clones = (TClonesArray*)*(void**)((char*)fWhere+fOffset);
334 } else {
335 clones = (TClonesArray*)((char*)fWhere+fOffset);
336 }
337 if (!fIsMember) fIsClone = true;
338 fClass = clones->GetClass();
339 } else if (fClass && fClass->GetCollectionProxy()) {
340 delete fCollection;
341 fCollection = fClass->GetCollectionProxy()->Generate();
342 fClass = fCollection->GetValueClass();
343 }
344
345 }
346 if (fClass) fClassName = fClass->GetName();
347 } else {
348 fClassName = be->GetClassName();
349 fClass = TClass::GetClass(fClassName);
350 }
351
352 if (be->GetType()==3) {
353 // top level TClonesArray
354
355 if (!fIsMember) fIsClone = true;
356 fIsaPointer = false;
357 fWhere = be->GetObject();
358
359 } else if (be->GetType()==4) {
360 // top level TClonesArray
361
362 fCollection = be->GetCollectionProxy()->Generate();
363 fIsaPointer = false;
364 fWhere = be->GetObject();
365
366 } else if (id<0) {
367 // top level object
368
369 fIsaPointer = false;
370 fWhere = be->GetObject();
371
372 } else if (be->GetType()==41) {
373
374 fCollection = be->GetCollectionProxy()->Generate();
375 fWhere = be->GetObject();
376 fOffset += be->GetOffset();
377
378 } else if (be->GetType()==31) {
379
380 fWhere = be->GetObject();
381 fOffset += be->GetOffset();
382
383 } else if (be->GetType()==2) {
384 // this might also be the right path for GetType()==1
385
386 fWhere = be->GetObject();
387
388 } else {
389
390 // fWhere = ((unsigned char*)fWhere) + fOffset;
391 fWhere = ((unsigned char*)be->GetObject()) + fOffset;
392
393 }
394 } else {
395 fClassName = fBranch->GetClassName();
396 fClass = TClass::GetClass(fClassName);
397 }
398
399
400 /*
401 fClassName = fBranch->GetClassName(); // What about TClonesArray?
402 if ( fBranch->IsA()==TBranchElement::Class() &&
403 ((TBranchElement*)fBranch)->GetType()==31 ||((TBranchElement*)fBranch)->GetType()==3 ) {
404
405 Int_t id = ((TBranchElement*)fBranch)->GetID();
406 if (id>=0) {
407
408 fElement = ((TStreamerElement*)(((TBranchElement*)fBranch)->GetInfo())->GetElements()->At(id));
409 fClass = fElement->GetClassPointer();
410 if (fClass) fClassName = fClass->GetName();
411
412 }
413 }
414 if (fClass==0 && fClassName.Length()) fClass = TClass::GetClass(fClassName);
415 */
416 //fprintf(stderr,"For %s fClass is %p which is %s\n",
417 // fBranchName.Data(),fClass,fClass==0?"not set":fClass->GetName());
418
419 if ( fBranch->IsA()==TBranchElement::Class() &&
420 (((TBranchElement*)fBranch)->GetType()==3 || fClass==TClonesArray::Class()) &&
421 !fIsMember ) {
422 fIsClone = true;
423 }
424
425 if (fIsMember) {
426 if ( fBranch->IsA()==TBranchElement::Class() &&
427 fClass==TClonesArray::Class() &&
428 (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
429
430 TBranchElement *bcount = ((TBranchElement*)fBranch)->GetBranchCount();
431 TString member;
432 if (bcount) {
433 TString bname = fBranch->GetName();
434 TString bcname = bcount->GetName();
435 member = bname.Remove(0,bcname.Length()+1);
436 } else {
437 member = fDataMember;
438 }
439
440 fMemberOffset = fClass->GetDataMemberOffset(member);
441
442 if (fMemberOffset<0) {
443 Error("Setup","%s",Form("Negative offset %d for %s in %s",
444 fMemberOffset,fBranch->GetName(),
445 bcount?bcount->GetName():"unknown"));
446 }
447
448 } else if (fClass) {
449
450 fElement = (TStreamerElement*)
451 fClass->GetStreamerInfo()->GetElements()->FindObject(fDataMember);
452 if (fElement)
453 fMemberOffset = fElement->GetOffset();
454 else {
455 // Need to compose the proper sub name
456
457 TString member;
458
459 member += fDataMember;
460 fMemberOffset = fClass->GetDataMemberOffset(member);
461
462 }
463 // The extra condition (fElement is not a TStreamerSTL) is to handle the case where fBranch is a
464 // TBranchElement and fElement is a TStreamerSTL. Without the extra condition we get an error
465 // message, although the vector (i.e. the TBranchElement) is accessible.
466 } else if (fBranch->IsA() != TBranch::Class() && fElement->IsA() != TStreamerBasicType::Class()
467 && fElement->IsA() != TStreamerSTL::Class()) {
468 Error("Setup","%s",Form("Missing TClass object for %s\n",fClassName.Data()));
469 }
470
471 if ( fBranch->IsA()==TBranchElement::Class()
472 && (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
473
474 fOffset = fMemberOffset;
475
476 } else {
477
478 fWhere = ((unsigned char*)fWhere) + fMemberOffset;
479 }
480 }
481 }
482 if (fClass==TClonesArray::Class()) fIsClone = true;
483 if (fWhere!=0) {
484 fInitialized = true;
485 return true;
486 } else {
487 return false;
488 }
489}
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:363
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 * 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:64
virtual char * GetAddress() const
Definition: TBranch.h:171
TTree * GetTree() const
Definition: TBranch.h:209
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2265
Int_t GetOffset() const
Definition: TBranch.h:192
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1725
The ROOT global object gROOT contains a list of all defined classes.
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:4452
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
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:2885
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:32
virtual void * GetValuePointer() const
Definition: TLeaf.h:92
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:78
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:137
TBranch * GetBranch() const
Definition: TLeaf.h:75
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
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
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