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