Logo ROOT  
Reference Guide
TLeaf.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 12/01/96
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
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 TLeaf
13\ingroup tree
14
15A TLeaf describes individual elements of a TBranch
16See TBranch structure in TTree.
17
18A TTree object is a list of TBranch.
19A TBranch object is a list of TLeaf. In most cases, the TBranch
20will have one TLeaf.
21A TLeaf describes the branch data types and holds the data.
22
23A few notes about the data held by the leaf. It can contain:
24 1. a single object or primitive (e.g., one float),
25 2. a fixed-number of objects (e.g., each entry has two floats).
26 The number of elements per entry is saved in `fLen`.
27 3. a dynamic number of primitives. The number of objects in each
28 entry is saved in the `fLeafCount` branch.
29
30Note options (2) and (3) can combined - if fLeafCount says an entry
31has 3 elements and fLen is 2, then there will be 6 objects in that
32entry.
33
34Additionally, `fNdata` is transient and generated on read to
35determine the necessary size of a buffer to hold event data;
36depending on the call-site, it may be sized larger than the number
37of elements
38
39*/
40
41#include "TLeaf.h"
42#include "TBranch.h"
43#include "TBuffer.h"
44#include "TTree.h"
45#include "TVirtualPad.h"
46#include "TBrowser.h"
47#include "strlcpy.h"
48
49#include <cctype>
50
52
53////////////////////////////////////////////////////////////////////////////////
54
56 : TNamed()
57 , fNdata(0)
58 , fLen(0)
59 , fLenType(0)
60 , fOffset(0)
61 , fIsRange(kFALSE)
62 , fIsUnsigned(kFALSE)
63 , fLeafCount(0)
64 , fBranch(0)
65 , fLeafCountValues(0)
66{
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// Create a Leaf.
71///
72/// See the TTree and TBranch constructors for explanation of parameters.
73
74TLeaf::TLeaf(TBranch *parent, const char* name, const char *)
75 : TNamed(name, name)
76 , fNdata(0)
77 , fLen(0)
78 , fLenType(4)
79 , fOffset(0)
80 , fIsRange(kFALSE)
81 , fIsUnsigned(kFALSE)
82 , fLeafCount(0)
83 , fBranch(parent)
84 , fLeafCountValues(0)
85{
87
88 if (fLen == -1) {
89 MakeZombie();
90 return;
91 }
92
93 const char *bracket = strchr(name, '[');
94 if (bracket) fName.ReplaceAll(bracket,"");
95}
96
97////////////////////////////////////////////////////////////////////////////////
98/// Copy constructor.
99
100TLeaf::TLeaf(const TLeaf& lf) :
101 TNamed(lf),
102 fNdata(lf.fNdata),
103 fLen(lf.fLen),
104 fLenType(lf.fLenType),
105 fOffset(lf.fOffset),
106 fIsRange(lf.fIsRange),
107 fIsUnsigned(lf.fIsUnsigned),
108 fLeafCount(lf.fLeafCount),
109 fBranch(lf.fBranch),
110 fLeafCountValues(nullptr)
111{
112}
113
114////////////////////////////////////////////////////////////////////////////////
115/// Assignment operator.
116
118{
119 if(this!=&lf) {
121 fNdata=lf.fNdata;
122 fLen=lf.fLen;
124 fOffset=lf.fOffset;
128 fBranch=lf.fBranch;
129 if (fLeafCountValues) {
131 fLeafCountValues->fValues.resize(0);
132 }
133 }
134 return *this;
135}
136
137////////////////////////////////////////////////////////////////////////////////
138/// Destructor.
139
141{
142 if (fBranch) {
144 fBranch = 0;
145 if (tree) {
146 TObjArray *lst = tree->GetListOfLeaves();
147 if (lst->GetLast()!=-1) lst->Remove(this);
148 }
149 }
150 fLeafCount = 0;
151 delete fLeafCountValues;
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Browse the content of this leaf.
156
158{
159 if (strchr(GetName(), '.')) {
160 fBranch->GetTree()->Draw(GetName(), "", b ? b->GetDrawOption() : "");
161 } else {
162 if ((fBranch->GetListOfLeaves()->GetEntries() > 1) ||
163 (strcmp(fBranch->GetName(), GetName()) != 0)) {
165 if (!name.EndsWith(".")) name += ".";
166 name += GetName();
167 fBranch->GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
168 } else {
169 fBranch->GetTree()->Draw(GetName(), "", b ? b->GetDrawOption() : "");
170 }
171 }
172 if (gPad) {
173 gPad->Update();
174 }
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Pack leaf elements in Basket output buffer.
179
181{
182}
183
184////////////////////////////////////////////////////////////////////////////////
185/// If the class supports it, generate an offset array base.
186///
187/// This class only returns `nullptr` on error.
189{
190 // In order to avoid a virtual call, we assume ROOT developers will override
191 // the default GenerateOffsetArray for cases where this function does not apply.
192
193 Int_t *retval = new Int_t[events];
194 if (R__unlikely(!retval || !fLeafCount)) {
195 delete [] retval;
196 return nullptr;
197 }
198
199 Long64_t orig_entry = std::max(fBranch->GetReadEntry(), 0LL); // -1 indicates to start at the beginning
200 const std::vector<Int_t> *countValues = fLeafCount->GetLeafCountValues(orig_entry, events);
201
202 if (!countValues || ((Int_t)countValues->size()) < events) {
203 Error("GenerateOffsetArrayBase", "The leaf %s could not retrieve enough entries from its branch count (%s), ask for %d and got %ld",
204 GetName(), fLeafCount->GetName(), events, (long)(countValues ? countValues->size() : -1));
205 delete [] retval;
206 return nullptr;
207 }
208
209 Int_t header = GetOffsetHeaderSize();
210 Int_t len = 0;
211 for (Int_t idx = 0, offset = base; idx < events; idx++) {
212 retval[idx] = offset;
213 len = (*countValues)[idx];
214 offset += fLenType * len + header;
215 }
216
217 return retval;
218}
219
220
221////////////////////////////////////////////////////////////////////////////////
222/// Return the full name (including the parent's branch names) of the leaf.
223
225{
226 TString branchname = GetBranch()->GetFullName();
227 if (branchname.Length() && (branchname[branchname.Length()-1] == '.'))
228 return branchname + GetName();
229 else
230 return branchname + "." + GetName();
231}
232
233////////////////////////////////////////////////////////////////////////////////
234/// Return a pointer to the counter of this leaf (if any) or store the number of elements that the leaf contains in
235/// countval.
236///
237/// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
238/// if nelem is a leaf name, return countval = 1 and the pointer to
239/// the leaf named nelem, otherwise return 0.
240/// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
241/// return countval = nelem and a null pointer.
242/// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2]
243/// where nelem and nelem2 are non-negative integers) then
244/// return countval = product of all dimension sizes and a null pointer.
245/// - If leaf name has the form var[... (and does not match the previous 2
246/// cases) return countval = -1 and null pointer;
247/// - Otherwise return countval = 1 and a null pointer.
248
250{
251 countval = 1;
252 const char* name = GetTitle();
253 char* bleft = (char*) strchr(name, '[');
254 if (!bleft) {
255 return 0;
256 }
257 bleft++;
258 Int_t nch = strlen(bleft);
259 char* countname = new char[nch+1];
260 strlcpy(countname, bleft, nch+1);
261 char* bright = (char*) strchr(countname, ']');
262 if (!bright) {
263 delete[] countname;
264 countname = 0;
265 countval = -1;
266 return 0;
267 }
268 char *bleft2 = (char*) strchr(countname, '[');
269 *bright = 0;
270 nch = strlen(countname);
271
272 // Now search a branch name with a leaf name = countname
273 if (fBranch == 0) {
274 Error("GetLeafCounter","TLeaf %s is not setup properly, fBranch is null.",GetName());
275 delete[] countname;
276 return 0;
277 }
278 if (fBranch->GetTree() == 0) {
279 Error("GetLeafCounter","For Leaf %s, the TBranch %s is not setup properly, fTree is null.",GetName(),fBranch->GetName());
280 delete[] countname;
281 return 0;
282 }
283 TTree* pTree = fBranch->GetTree();
284
285 TLeaf* leaf = (TLeaf*) GetBranch()->GetListOfLeaves()->FindObject(countname);
286 if (leaf == 0) {
287 // Try outside the branch:
288 leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
289 }
290 //if not found, make one more trial in case the leaf name has a "."
291 if (!leaf && strchr(GetName(), '.')) {
292 char* withdot = new char[strlen(GetName())+strlen(countname)+1];
293 strcpy(withdot, GetName());
294 char* lastdot = strrchr(withdot, '.');
295 strcpy(lastdot, countname);
296 leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(withdot);
297 delete[] withdot;
298 withdot = 0;
299 }
300 if (!leaf && strchr(countname,'.')) {
301 // Not yet found and the countname has a dot in it, let's try
302 // to find the leaf using its full name
303 leaf = pTree->FindLeaf(countname);
304 }
305 Int_t i = 0;
306 if (leaf) {
307 countval = 1;
308 leaf->SetRange();
309 if (bleft2) {
310 sscanf(bleft2, "[%d]", &i);
311 countval *= i;
312 }
313 bleft = bleft2;
314 while (bleft) {
315 bleft2++;
316 bleft = (char*) strchr(bleft2, '[');
317 if (!bleft) {
318 break;
319 }
320 sscanf(bleft, "[%d]", &i);
321 countval *= i;
322 bleft2 = bleft;
323 }
324 delete[] countname;
325 countname = 0;
326 return leaf;
327 }
328 // not found in a branch/leaf. Is it a numerical value?
329 for (i = 0; i < nch; i++) {
330 if (!isdigit(countname[i])) {
331 delete[] countname;
332 countname = 0;
333 countval = -1;
334 return 0;
335 }
336 }
337 sscanf(countname, "%d", &countval);
338 if (bleft2) {
339 sscanf(bleft2, "[%d]", &i);
340 countval *= i;
341 }
342 bleft = bleft2;
343 while (bleft) {
344 bleft2++;
345 bleft = (char*) strchr(bleft2, '[');
346 if (!bleft) {
347 break;
348 }
349 sscanf(bleft, "[%d]", &i);
350 countval *= i;
351 bleft2 = bleft;
352 }
353
354 delete[] countname;
355 countname = 0;
356 return 0;
357}
358
359////////////////////////////////////////////////////////////////////////////////
360/// If this branch is a branch count, return the set of collection size for
361/// the entry range requested
362/// start: first entry to read and return information about
363/// len: number of entries to read.
365{
366 if (len <= 0 || !IsRange())
367 return nullptr;
368
369 if (fLeafCountValues) {
370 if (fLeafCountValues->fStartEntry == start && len < (Long64_t)fLeafCountValues->fValues.size())
371 {
372 return &fLeafCountValues->fValues;
373 }
374 if (start >= fLeafCountValues->fStartEntry &&
375 (start+len) <= (Long64_t)(fLeafCountValues->fStartEntry + fLeafCountValues->fValues.size()))
376 {
377 auto &values(fLeafCountValues->fValues);
378 values.erase(values.begin(), values.begin() + start-fLeafCountValues->fStartEntry);
379 return &values;
380 }
381 } else {
383 }
384
385
386 fLeafCountValues->fValues.clear();
387 fLeafCountValues->fValues.reserve(len);
389
390 auto branch = GetBranch();
391 Long64_t orig_leaf_entry = branch->GetReadEntry();
392 for (Long64_t idx = 0; idx < len; ++idx) {
393 branch->GetEntry(start + idx);
394 auto size = static_cast<Int_t>(GetValue());
395 fLeafCountValues->fValues.push_back( size );
396 }
397 branch->GetEntry(orig_leaf_entry);
398 return &(fLeafCountValues->fValues);
399}
400
401////////////////////////////////////////////////////////////////////////////////
402/// Return the number of effective elements of this leaf, for the current entry.
403
405{
406 if (fLeafCount) {
407 // -- We are a varying length array.
408 Int_t len = Int_t(fLeafCount->GetValue());
409 if (len > fLeafCount->GetMaximum()) {
410 Error("GetLen", "Leaf counter is greater than maximum! leaf: '%s' len: %d max: %d", GetName(), len, fLeafCount->GetMaximum());
411 len = fLeafCount->GetMaximum();
412 }
413 return len * fLen;
414 } else {
415 // -- We are a fixed size thing.
416 return fLen;
417 }
418}
419
420////////////////////////////////////////////////////////////////////////////////
421/// Helper routine for TLeafX::SetAddress.
422///
423/// The return value is non-zero if we owned the old
424/// value buffer and must delete it now. The size
425/// of the value buffer is recalculated and stored,
426/// and a decision is made whether or not we own the
427/// new value buffer.
428
429Int_t TLeaf::ResetAddress(void* addr, Bool_t calledFromDestructor)
430{
431 // The kNewValue bit records whether or not we own
432 // the current value buffer or not. If we own it,
433 // then we are responsible for deleting it.
434 Bool_t deleteValue = kFALSE;
435 if (TestBit(kNewValue)) {
436 deleteValue = kTRUE;
437 }
438 // If we are not being called from a destructor,
439 // recalculate the value buffer size and decide
440 // whether or not we own the new value buffer.
441 if (!calledFromDestructor) {
442 // -- Recalculate value buffer size and decide ownership of value.
443 if (fLeafCount) {
444 // -- Varying length array data member.
445 fNdata = (fLeafCount->GetMaximum() + 1) * fLen;
446 } else {
447 // -- Fixed size data member.
448 fNdata = fLen;
449 }
450 // If we were provided an address, then we do not own
451 // the value, otherwise we do and must delete it later,
452 // keep track of this with bit kNewValue.
453 if (addr) {
455 } else {
457 }
458 }
459 return deleteValue;
460}
461
462////////////////////////////////////////////////////////////////////////////////
463/// Set the leaf count of this leaf.
464
466{
467 if (IsZombie() && (fLen == -1) && leaf) {
468 // The constructor noted that it could not find the
469 // leafcount. Now that we did find it, let's remove
470 // the side-effects.
472 fLen = 1;
473 }
474 fLeafCount = leaf;
475}
476
477////////////////////////////////////////////////////////////////////////////////
478/// Stream a class object.
479
480void TLeaf::Streamer(TBuffer &b)
481{
482 if (b.IsReading()) {
483 UInt_t R__s, R__c;
484 Version_t R__v = b.ReadVersion(&R__s, &R__c);
485 if (R__v > 1) {
486 b.ReadClassBuffer(TLeaf::Class(), this, R__v, R__s, R__c);
487 } else {
488 // -- Process old versions before automatic schema evolution.
489 TNamed::Streamer(b);
490 b >> fLen;
491 b >> fLenType;
492 b >> fOffset;
493 b >> fIsRange;
494 b >> fIsUnsigned;
495 b >> fLeafCount;
496 b.CheckByteCount(R__s, R__c, TLeaf::IsA());
497 }
498 if (!fLen) {
499 fLen = 1;
500 }
501 // We do not own the value buffer right now.
503 SetAddress();
504 } else {
505 b.WriteClassBuffer(TLeaf::Class(), this);
506 }
507}
508
void Class()
Definition: Class.C:29
#define R__unlikely(expr)
Definition: RConfig.hxx:595
#define b(i)
Definition: RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Definition: RtypesCore.h:45
short Version_t
Definition: RtypesCore.h:65
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
char name[80]
Definition: TGX11.cxx:110
#define gPad
Definition: TVirtualPad.h:287
A TTree is a list of TBranches.
Definition: TBranch.h:89
TTree * GetTree() const
Definition: TBranch.h:248
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition: TBranch.cxx:1956
Long64_t GetReadEntry() const
Definition: TBranch.h:233
TObjArray * GetListOfLeaves()
Definition: TBranch.h:243
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:57
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:183
virtual Bool_t IsRange() const
Definition: TLeaf.h:149
Int_t fLenType
Number of bytes for this data type.
Definition: TLeaf.h:73
virtual const Counts_t * GetLeafCountValues(Long64_t start, Long64_t len)
If this branch is a branch count, return the set of collection size for the entry range requested sta...
Definition: TLeaf.cxx:364
virtual Int_t GetMaximum() const
Definition: TLeaf.h:134
virtual void Browse(TBrowser *b)
Browse the content of this leaf.
Definition: TLeaf.cxx:157
Int_t fLen
Number of fixed length elements in the leaf's data.
Definition: TLeaf.h:72
Int_t fNdata
! Number of elements in fAddress data buffer.
Definition: TLeaf.h:71
virtual Int_t GetLen() const
Return the number of effective elements of this leaf, for the current entry.
Definition: TLeaf.cxx:404
Bool_t fIsUnsigned
(=kTRUE if unsigned, kFALSE otherwise)
Definition: TLeaf.h:76
virtual ~TLeaf()
Destructor.
Definition: TLeaf.cxx:140
TLeaf & operator=(const TLeaf &)
Assignment operator.
Definition: TLeaf.cxx:117
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:185
virtual TLeaf * GetLeafCounter(Int_t &countval) const
Return a pointer to the counter of this leaf (if any) or store the number of elements that the leaf c...
Definition: TLeaf.cxx:249
virtual void SetRange(Bool_t range=kTRUE)
Definition: TLeaf.h:165
Int_t * GenerateOffsetArrayBase(Int_t base, Int_t events) const
If the class supports it, generate an offset array base.
Definition: TLeaf.cxx:188
virtual void FillBasket(TBuffer &b)
Pack leaf elements in Basket output buffer.
Definition: TLeaf.cxx:180
TLeaf()
Definition: TLeaf.cxx:55
TBranch * GetBranch() const
Definition: TLeaf.h:116
Int_t fOffset
Offset in ClonesArray object (if one)
Definition: TLeaf.h:74
virtual Int_t GetOffsetHeaderSize() const
Definition: TLeaf.h:61
Int_t ResetAddress(void *add, Bool_t calledFromDestructor=kFALSE)
Helper routine for TLeafX::SetAddress.
Definition: TLeaf.cxx:429
TBranch * fBranch
! Pointer to supporting branch (we do not own the branch)
Definition: TLeaf.h:78
TLeaf * fLeafCount
Pointer to Leaf count if variable length (we do not own the counter)
Definition: TLeaf.h:77
Bool_t fIsRange
(=kTRUE if leaf has a range, kFALSE otherwise). This is equivalent to being a 'leafcount'....
Definition: TLeaf.h:75
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition: TLeaf.h:96
virtual void SetLeafCount(TLeaf *leaf)
Set the leaf count of this leaf.
Definition: TLeaf.cxx:465
virtual TString GetFullName() const
Return the full name (including the parent's branch names) of the leaf.
Definition: TLeaf.cxx:224
LeafCountValues * fLeafCountValues
! Cache of collection/array sizes
Definition: TLeaf.h:79
std::vector< Int_t > Counts_t
Definition: TLeaf.h:65
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TString fName
Definition: TNamed.h:32
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition: TNamed.cxx:51
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:415
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:577
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:719
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
@ kZombie
object ctor failed
Definition: TObject.h:79
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:149
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:696
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
void MakeZombie()
Definition: TObject.h:49
void ResetBit(UInt_t f)
Definition: TObject.h:186
Basic string class.
Definition: TString.h:136
Ssiz_t Length() const
Definition: TString.h:410
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
A TTree represents a columnar dataset.
Definition: TTree.h:79
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:485
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:428
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4882
Definition: tree.py:1
Counts_t fValues
Definition: TLeaf.h:67
Long64_t fStartEntry
! entry number of corresponding to element 0 of the vector.
Definition: TLeaf.h:68