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 "TCollection.h" // TRangeStaticCast
22#include "TStreamerElement.h"
23#include "TStreamerInfo.h"
24#include "ROOT/InternalTreeUtils.hxx" // GetFileNamesFromTree, GetTreeFullPaths
25
26#include <string>
27#include <string_view>
28
29
30using namespace ROOT::Internal;
31
32namespace {
33/**
34 * \brief Find if the input branch name is the prefix for other sub-branches in the same tree.
35 */
36bool AreThereSubBranches(std::string_view parentBrName, TTree &tree)
37{
38 const std::string prefix = [&parentBrName]() {
39 if (parentBrName.back() == '.')
40 return std::string(parentBrName);
41 return std::string(parentBrName) + '.';
42 }();
43
44 for (auto *leaf : ROOT::Detail::TRangeStaticCast<TLeaf>(tree.GetListOfLeaves()))
45 // Compares the prefix string with the leaf name, checking if the first
46 // `prefix.size()` characters match those of the prefix, i.e. if the leaf
47 // name starts with the prefix
48 if (prefix.compare(0, prefix.size(), leaf->GetName(), prefix.size()) == 0)
50 return false;
51}
52} // namespace
53
54////////////////////////////////////////////////////////////////////////////////
55/// Constructor.
56
58 fDirector(nullptr), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
59 fHasLeafCount(false), fBranchName(""), fParent(nullptr), fDataMember(""),
60 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
61 fBranch(nullptr), fBranchCount(nullptr),
62 fNotify(this),
63 fRead(-1), fWhere(nullptr),fCollection(nullptr)
64{
65};
66
67////////////////////////////////////////////////////////////////////////////////
68/// Constructor.
69
71 const char* name) :
72 fDirector(boss), fInitialized(false), fIsMember(false), fIsClone(false), fIsaPointer(false),
73 fHasLeafCount(false), fBranchName(top), fParent(nullptr), fDataMember(""),
74 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
75 fBranch(nullptr), fBranchCount(nullptr),
76 fNotify(this),
77 fRead(-1), fWhere(nullptr),fCollection(nullptr)
78{
79 if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.' && name) {
80 ((TString&)fBranchName).Append(".");
81 }
82 if (name) ((TString&)fBranchName).Append(name);
83 boss->Attach(this);
84}
85
86////////////////////////////////////////////////////////////////////////////////
87/// Constructor.
88
90 fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
91 fHasLeafCount(false), fBranchName(top), fParent(nullptr), fDataMember(membername),
92 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
93 fBranch(nullptr), fBranchCount(nullptr),
94 fNotify(this),
95 fRead(-1), fWhere(nullptr),fCollection(nullptr)
96{
97 if (name && strlen(name)) {
98 if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
99 ((TString&)fBranchName).Append(".");
100 }
101 ((TString&)fBranchName).Append(name);
102 }
103 boss->Attach(this);
104}
105
106////////////////////////////////////////////////////////////////////////////////
107/// Constructor.
108
110 const char* name) :
111 fDirector(boss), fInitialized(false), fIsMember(true), fIsClone(false), fIsaPointer(false),
112 fHasLeafCount(false), fBranchName(top), fParent(parent), fDataMember(membername),
113 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
114 fBranch(nullptr), fBranchCount(nullptr),
115 fNotify(this),
116 fRead(-1), fWhere(nullptr),fCollection(nullptr)
118 if (name && strlen(name)) {
119 if (fBranchName.Length() && fBranchName[fBranchName.Length()-1]!='.') {
120 ((TString&)fBranchName).Append(".");
122 ((TString&)fBranchName).Append(name);
123 }
124 boss->Attach(this);
125}
126
127////////////////////////////////////////////////////////////////////////////////
128/// Constructor.
129
131 fDirector(boss), fInitialized(false), fIsMember(membername != nullptr && membername[0]), fIsClone(false), fIsaPointer(false),
132 fHasLeafCount(false), fBranchName(branch->GetName()), fParent(nullptr), fDataMember(membername),
133 fClassName(""), fClass(nullptr), fElement(nullptr), fMemberOffset(0), fOffset(0), fArrayLength(1),
134 fBranch(nullptr), fBranchCount(nullptr),
135 fNotify(this),
136 fRead(-1), fWhere(nullptr),fCollection(nullptr)
137{
138 boss->Attach(this);
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// For a fullBranchName that might contain a leading friend tree path (but
143/// access elements designating a leaf), but the leaf name such that it matches
144/// the "path" to branch.
145
147{
148 // ROOT-10046: Here we need to ask for the tree with GetTree otherwise, if directorTree
149 // is a chain, this check is bogus and a bug can occur (ROOT-10046)
150 if (directorTree->GetTree() == branch->GetTree())
151 return branch->GetFullName().Data();
152
153 // Friend case:
154 std::string sFullBranchName = fullBranchName;
155 std::string::size_type pos = sFullBranchName.rfind(branch->GetFullName());
156 if (pos != std::string::npos) {
157 sFullBranchName.erase(pos);
158 sFullBranchName += branch->GetFullName();
159 }
160 return sFullBranchName;
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Constructor taking the branch name, possibly of a friended tree.
165/// Used by TTreeReaderValue in place of TFriendProxy.
166
168 const char *membername, bool suppressMissingBranchError)
169 : fDirector(boss),
170 fInitialized(false),
171 fIsMember(membername != nullptr && membername[0]),
172 fIsClone(false),
173 fIsaPointer(false),
174 fHasLeafCount(false),
175 fSuppressMissingBranchError(suppressMissingBranchError),
176 fBranchName(GetFriendBranchName(boss->GetTree(), branch, branchname)),
177 fParent(nullptr),
178 fDataMember(membername),
179 fClassName(""),
180 fClass(nullptr),
181 fElement(nullptr),
182 fMemberOffset(0),
183 fOffset(0),
184 fArrayLength(1),
185 fBranch(nullptr),
186 fBranchCount(nullptr),
187 fNotify(this),
188 fRead(-1),
189 fWhere(nullptr),
190 fCollection(nullptr)
191{
192 // Constructor.
193
194 boss->Attach(this);
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Typical Destructor
199
201{
202 if (fNotify.IsLinked() && fDirector && fDirector->GetTree())
203 fNotify.RemoveLink(*(fDirector->GetTree()));
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Completely reset the object.
208
210{
211 fWhere = nullptr;
212 fBranch = nullptr;
213 fBranchCount = nullptr;
214 fRead = -1;
215 fClass = nullptr;
216 fElement = nullptr;
217 fMemberOffset = 0;
218 fOffset = 0;
219 fArrayLength = 1;
220 fIsClone = false;
221 fInitialized = false;
222 fHasLeafCount = false;
223 delete fCollection;
224 fCollection = nullptr;
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Display the content of the object
229
231{
232 std::cout << "fBranchName " << fBranchName << std::endl;
233 //std::cout << "fTree " << fDirector->fTree << std::endl;
234 std::cout << "fBranch " << fBranch << std::endl;
235 if (fHasLeafCount)
236 std::cout << "fLeafCount " << fLeafCount << std::endl;
237 else if (fBranchCount)
238 std::cout << "fBranchCount " << fBranchCount << std::endl;
239}
240
241
242////////////////////////////////////////////////////////////////////////////////
243/// Initialize/cache the necessary information.
244
246{
247 // Should we check the type?
248
249 if (!fDirector->GetTree()) {
250 return false;
251 }
252 if (!fNotify.IsLinked()) {
253 fNotify.PrependLink(*fDirector->GetTree());
254 }
255 if (fParent) {
256
257 if (!fParent->Setup()) {
258 return false;
259 }
260
261 TClass *pcl = fParent->GetClass();
262 R__ASSERT(pcl);
263
264 if (pcl==TClonesArray::Class()) {
265 // We always skip the clones array
266
267 Int_t i = fDirector->GetReadEntry();
268 if (i<0) fDirector->SetReadEntry(0);
269 if (fParent->Read()) {
270 if (i<0) fDirector->SetReadEntry(i);
271
273 clones = (TClonesArray*)fParent->GetStart();
274
275 if (clones) pcl = clones->GetClass();
276 }
277 } else if (pcl->GetCollectionProxy()) {
278 // We always skip the collections.
279
280 if (fCollection) delete fCollection;
281 fCollection = pcl->GetCollectionProxy()->Generate();
282 pcl = fCollection->GetValueClass();
283 if (pcl == nullptr) {
284 // coverity[dereference] fparent is checked jus a bit earlier and can not be null here
285 Error("Setup","Not finding TClass for collection for the data member %s seems no longer be in class %s",fDataMember.Data(),fParent->GetClass()->GetName());
286 return false;
287 }
288 }
289
290 fElement = (TStreamerElement*)pcl->GetStreamerInfo()->GetStreamerElement(fDataMember, fOffset);
291 if (fElement) {
292 fIsaPointer = fElement->IsaPointer();
293 fClass = fElement->GetClassPointer();
294 fMemberOffset = fElement->GetOffset();
295 fArrayLength = fElement->GetArrayLength();
296 fValueSize = fElement->GetSize();
297 } else {
298 Error("Setup","Data member %s seems no longer be in class %s",fDataMember.Data(),pcl->GetName());
299 return false;
300 }
301
302 fIsClone = (fClass==TClonesArray::Class());
303
304 fWhere = fParent->fWhere; // not really used ... it is reset by GetStart and GetClStart
305
306 if (fParent->IsaPointer()) {
307 // fprintf(stderr,"non-split pointer de-referencing non implemented yet \n");
308 // nothing to do!
309 } else {
310 // Accumulate offsets.
311 // or not!? fOffset = fMemberOffset = fMemberOffset + fParent->fOffset;
312 }
313
314 // This is not sufficient for following pointers
315
316 } else {
317
318 // This does not allow (yet) to precede the branch name with
319 // its mother's name
320 fBranch = fDirector->GetTree()->GetBranch(fBranchName.Data());
321 if (!fBranch) {
322 if (!fSuppressMissingBranchError && !AreThereSubBranches(fBranchName.View(), *fDirector->GetTree())) {
323 // The next error refers specifically to the situation where the branch identified by fBranchName
324 // is not present and that is not expected. An example is when traversing a chain of files, the branch
325 // is missing from the file that we are switching into.
326 // Conversely, there are situations where the missing branch is indeed expected. A notable example is when
327 // the TTree contains a split object, the branch referring to the whole object type will actually be elided
328 // and will not be found by `TTree::GetBranch`, only the data members will be present as sub branches.
329 auto *tree = fDirector->GetTree()->GetTree(); // Double GetTree to extract the current TTree being processed
330 Error("TBranchProxy::Setup()", "%s",
331 Form("Branch '%s' is not available from tree '%s' in file '%s'.", fBranchName.Data(),
334 }
335 return false;
336 }
337
338 fWhere = (double*)fBranch->GetAddress();
339
340 if (!fWhere && fBranch->IsA()==TBranchElement::Class()
341 && ((TBranchElement*)fBranch)->GetMother()) {
342
343 TBranchElement* be = ((TBranchElement*)fBranch);
344
345 be->GetMother()->SetAddress(nullptr);
346 fWhere = (double*)fBranch->GetAddress();
347
348 }
349 if (fBranch->IsA()==TBranch::Class()) {
350 TLeaf *leaf2 = nullptr;
351 if (fDataMember.Length()) {
352 leaf2 = fBranch->GetLeaf(fDataMember);
353 } else if (!fWhere) {
354 leaf2 = (TLeaf*)fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
355 fWhere = leaf2->GetValuePointer();
356 }
357 if (leaf2) {
358 fWhere = leaf2->GetValuePointer();
359 fArrayLength = leaf2->GetLen();
360 fValueSize = leaf2->GetLenType();
361 if (leaf2->GetLeafCount()) {
362 fLeafCount = leaf2->GetLeafCount();
363 fHasLeafCount = true;
364 }
365 }
366 } else if (fBranch->IsA() == TBranchElement::Class()) {
367 // Calculate fBranchCount for a leaf.
368 TLeaf *leaf = (TLeaf*) fBranch->GetListOfLeaves()->At(0); // fBranch->GetLeaf(fLeafname);
369 if (leaf)
370 leaf = leaf->GetLeafCount();
371 if (leaf) {
372 fBranchCount = dynamic_cast<TBranchElement*>(leaf->GetBranch());
373 }
374 }
375
376 if (!fWhere) {
377 fBranch->SetupAddresses();
378 fWhere = (double*)fBranch->GetAddress();
379 }
380
381
382 if (fWhere && fBranch->IsA()==TBranchElement::Class()) {
383
384 TBranchElement* be = ((TBranchElement*)fBranch);
385
386 TStreamerInfo * info = be->GetInfo();
387 Int_t id = be->GetID();
388 if (be->GetType() == 3) {
389 fClassName = "TClonesArray";
391 } else if (id>=0) {
392 fOffset = info->GetElementOffset(id);
393 fElement = (TStreamerElement*)info->GetElements()->At(id);
394 fIsaPointer = fElement->IsaPointer();
395 fClass = fElement->GetClassPointer();
396 fValueSize = fElement->GetSize();
397
398 if ((fIsMember || (be->GetType()!=3 && be->GetType() !=4))
399 && (be->GetType()!=31 && be->GetType()!=41)) {
400
402 Int_t i = be->GetTree()->GetReadEntry();
403 if (i<0) i = 0;
404 be->GetEntry(i);
405
407 if ( fIsMember && be->GetType()==3 ) {
408 clones = (TClonesArray*)be->GetObject();
409 } else if (fIsaPointer) {
410 clones = (TClonesArray*)*(void**)((char*)fWhere+fOffset);
411 } else {
412 clones = (TClonesArray*)((char*)fWhere+fOffset);
413 }
414 if (!fIsMember) fIsClone = true;
415 fClass = clones->GetClass();
416 } else if (fClass && fClass->GetCollectionProxy()) {
417 delete fCollection;
418 fCollection = fClass->GetCollectionProxy()->Generate();
419 fClass = fCollection->GetValueClass();
420 }
421
422 }
423 if (fClass) fClassName = fClass->GetName();
424 } else {
425 fClassName = be->GetClassName();
426 fClass = TClass::GetClass(fClassName);
427 }
428
429 if (be->GetType()==3) {
430 // top level TClonesArray
431
432 if (!fIsMember) fIsClone = true;
433 fIsaPointer = false;
434 fWhere = be->GetObject();
435 fValueSize = static_cast<TClonesArray *>(fWhere)->GetClass()->Size();
436
437 } else if (be->GetType()==4) {
438 // top level TClonesArray
439
440 fCollection = be->GetCollectionProxy()->Generate();
441 fIsaPointer = false;
442 fWhere = be->GetObject();
443
444 } else if (id<0) {
445 // top level object
446
447 fIsaPointer = false;
448 fWhere = be->GetObject();
449
450 } else if (be->GetType()==41) {
451
452 fCollection = be->GetCollectionProxy()->Generate();
453 fWhere = be->GetObject();
454 fOffset += be->GetOffset();
455
456 } else if (be->GetType()==31) {
457
458 fWhere = be->GetObject();
459 fOffset += be->GetOffset();
460
461 } else if (be->GetType()==2) {
462 // this might also be the right path for GetType()==1
463
464 fWhere = be->GetObject();
465
466 } else {
467
468 // fWhere = ((unsigned char*)fWhere) + fOffset;
469 fWhere = ((unsigned char*)be->GetObject()) + fOffset;
470
471 }
472 } else if (fBranch->IsA() == TBranchObject::Class()) {
473 fIsaPointer = true; // this holds for all cases we test
474 fClassName = fBranch->GetClassName();
475 fClass = TClass::GetClass(fClassName);
476 } else {
477 fClassName = fBranch->GetClassName();
478 fClass = TClass::GetClass(fClassName);
479 }
480
481 /*
482 fClassName = fBranch->GetClassName(); // What about TClonesArray?
483 if ( fBranch->IsA()==TBranchElement::Class() &&
484 ((TBranchElement*)fBranch)->GetType()==31 ||((TBranchElement*)fBranch)->GetType()==3 ) {
485
486 Int_t id = ((TBranchElement*)fBranch)->GetID();
487 if (id>=0) {
488
489 fElement = ((TStreamerElement*)(((TBranchElement*)fBranch)->GetInfo())->GetElements()->At(id));
490 fClass = fElement->GetClassPointer();
491 if (fClass) fClassName = fClass->GetName();
492
493 }
494 }
495 if (fClass==0 && fClassName.Length()) fClass = TClass::GetClass(fClassName);
496 */
497 //fprintf(stderr,"For %s fClass is %p which is %s\n",
498 // fBranchName.Data(),fClass,fClass==0?"not set":fClass->GetName());
499
500 if ( fBranch->IsA()==TBranchElement::Class() &&
501 (((TBranchElement*)fBranch)->GetType()==3 || fClass==TClonesArray::Class()) &&
502 !fIsMember ) {
503 fIsClone = true;
504 }
505
506 if (fIsMember) {
507 if ( fBranch->IsA()==TBranchElement::Class() &&
509 (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
510
511 TBranchElement *bcount = ((TBranchElement*)fBranch)->GetBranchCount();
513 if (bcount) {
514 TString bname = fBranch->GetName();
515 TString bcname = bcount->GetName();
516 member = bname.Remove(0,bcname.Length()+1);
517 } else {
518 member = fDataMember;
519 }
520
521 fMemberOffset = fClass->GetDataMemberOffset(member);
522
523 if (fMemberOffset < 0) {
524 Error("Setup","%s",Form("Negative offset %d for %s in %s",
525 fMemberOffset,fBranch->GetName(),
526 bcount?bcount->GetName():"unknown"));
527 fMemberOffset = 0;
528 } else if (fMemberOffset == TVirtualStreamerInfo::kMissing) {
529 Error("Setup", "%s",
530 Form("Missing data member in a TClonesArray, %s in %s and %s", fDataMember.Data(),
531 fBranch->GetName(), bcount ? bcount->GetName() : "unknown"));
532 fMemberOffset = 0;
533 }
534
535 } else if (fParent && fClass) {
536
537 fElement = (TStreamerElement*)
538 fClass->GetStreamerInfo()->GetElements()->FindObject(fDataMember);
539 if (fElement) {
540 fMemberOffset = fElement->GetOffset();
541 fValueSize = fElement->GetSize();
542 } else {
543 // Need to compose the proper sub name
544
546
547 member += fDataMember;
548 fMemberOffset = fClass->GetDataMemberOffset(member);
549 }
550 if (fMemberOffset < 0) {
551 Error("Setup", "%s",
552 Form("Negative offset %d for %s in %s, class: %s", fMemberOffset, fDataMember.Data(),
553 fBranch->GetName(), fClass->GetName()));
554 fMemberOffset = 0;
555 } else if (fMemberOffset == TVirtualStreamerInfo::kMissing) {
556 Error("Setup", "%s",
557 Form("Missing data member %s in %s, class: %s", fDataMember.Data(), fBranch->GetName(),
558 fClass->GetName()));
559 fMemberOffset = 0;
560 }
561
562 // The extra condition (fElement is not a TStreamerSTL) is to handle the case where fBranch is a
563 // TBranchElement and fElement is a TStreamerSTL. Without the extra condition we get an error
564 // message, although the vector (i.e. the TBranchElement) is accessible.
565 } else if (fParent && fBranch->IsA() != TBranch::Class() && fElement->IsA() != TStreamerBasicType::Class() &&
566 fElement->IsA() != TStreamerSTL::Class()) {
567 Error("Setup", "%s", Form("Missing TClass object for %s", fClassName.Data()));
568 }
569
570 if ( fBranch->IsA()==TBranchElement::Class()
571 && (((TBranchElement*)fBranch)->GetType()==31 || ((TBranchElement*)fBranch)->GetType()==3) ) {
572
573 fOffset = fMemberOffset;
574
575 } else {
576
577 fWhere = ((unsigned char*)fWhere) + fMemberOffset;
578 }
579 }
580 }
581 if (fClass==TClonesArray::Class()) fIsClone = true;
582 if (fWhere!=nullptr) {
583 fInitialized = true;
584 return true;
585 } else {
586 return false;
587 }
588}
size_t fValueSize
Cppyy::TCppType_t fClass
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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...
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
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.
A Branch for the case of an object.
static TClass * Class()
void SetupAddresses() override
If the branch address is not set, we set all addresses starting with the top level parent branch.
TClass * IsA() const override
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
static TClass * Class()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
Int_t Size() const
Return size of object of this class.
Definition TClass.cxx:5743
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:2973
An array of clone (identical) objects.
static TClass * Class()
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
static TClass * Class()
Describe one element (data member) to be Streamed.
Describes a persistent version of a class.
static TClass * Class()
Basic string class.
Definition TString.h:138
TString & Remove(Ssiz_t pos)
Definition TString.h:693
A TTree represents a columnar dataset.
Definition TTree.h:89
std::vector< std::string > GetTreeFullPaths(const TTree &tree)
std::vector< std::string > GetFileNamesFromTree(const TTree &tree)
TClass * GetClass(T *)
Definition TClass.h:679