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