Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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(false)
62 , fIsUnsigned(false)
63 , fLeafCount(nullptr)
64 , fBranch(nullptr)
65 , fLeafCountValues(nullptr)
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(false)
81 , fIsUnsigned(false)
82 , fLeafCount(nullptr)
83 , fBranch(parent)
84 , fLeafCountValues(nullptr)
85{
87
88 if (fLen == -1) {
89 MakeZombie();
90 return;
91 }
92
93 const char *bracket = strchr(name, '[');
95}
96
97////////////////////////////////////////////////////////////////////////////////
98/// Copy constructor.
99
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;
123 fLenType=lf.fLenType;
124 fOffset=lf.fOffset;
125 fIsRange=lf.fIsRange;
126 fIsUnsigned=lf.fIsUnsigned;
127 fLeafCount=lf.fLeafCount;
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) {
143 TTree* tree = fBranch->GetTree();
144 fBranch = nullptr;
145 if (tree) {
146 TObjArray *lst = tree->GetListOfLeaves();
147 if (lst->GetLast()!=-1) lst->Remove(this);
148 }
149 }
150 fLeafCount = nullptr;
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{
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 auto slash = fTitle.First("/"); // for truncated types D32 F16
254 const char *name = sname.Data();
255 char* bleft = (char*) strchr(name, '[');
256 if (!bleft) {
257 return nullptr;
258 }
259 bleft++;
261 char* countname = new char[nch+1];
263 char* bright = (char*) strchr(countname, ']');
264 if (!bright) {
265 delete[] countname;
266 countname = nullptr;
267 countval = -1;
268 return nullptr;
269 }
270 char *bleft2 = (char*) strchr(countname, '[');
271 *bright = 0;
273
274 // Now search a branch name with a leaf name = countname
275 if (fBranch == nullptr) {
276 Error("GetLeafCounter","TLeaf %s is not setup properly, fBranch is null.",GetName());
277 delete[] countname;
278 return nullptr;
279 }
280 if (fBranch->GetTree() == nullptr) {
281 Error("GetLeafCounter","For Leaf %s, the TBranch %s is not setup properly, fTree is null.",GetName(),fBranch->GetName());
282 delete[] countname;
283 return nullptr;
284 }
286
288 if (leaf == nullptr) {
289 // Try outside the branch:
290 leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(countname);
291 }
292 //if not found, make one more trial in case the leaf name has a "."
293 if (!leaf && strchr(GetName(), '.')) {
294 char* withdot = new char[strlen(GetName())+strlen(countname)+1];
296 char* lastdot = strrchr(withdot, '.');
298 leaf = (TLeaf*) pTree->GetListOfLeaves()->FindObject(withdot);
299 delete[] withdot;
300 withdot = nullptr;
301 }
302 if (!leaf && strchr(countname,'.')) {
303 // Not yet found and the countname has a dot in it, let's try
304 // to find the leaf using its full name
305 leaf = pTree->FindLeaf(countname);
306 }
307 Int_t i = 0;
308 if (leaf) {
309 countval = 1;
310 leaf->SetRange();
311 if (bleft2) {
312 sscanf(bleft2, "[%d]", &i);
313 countval *= i;
314 }
315 bleft = bleft2;
316 while (bleft) {
317 bleft2++;
318 bleft = (char*) strchr(bleft2, '[');
319 if (!bleft) {
320 break;
321 }
322 sscanf(bleft, "[%d]", &i);
323 countval *= i;
324 bleft2 = bleft;
325 }
326 delete[] countname;
327 countname = nullptr;
328 return leaf;
329 }
330 // not found in a branch/leaf. Is it a numerical value?
331 for (i = 0; i < nch; i++) {
332 if (!isdigit(countname[i])) {
333 delete[] countname;
334 countname = nullptr;
335 countval = -1;
336 return nullptr;
337 }
338 }
339 sscanf(countname, "%d", &countval);
340 if (bleft2) {
341 sscanf(bleft2, "[%d]", &i);
342 countval *= i;
343 }
344 bleft = bleft2;
345 while (bleft) {
346 bleft2++;
347 bleft = (char*) strchr(bleft2, '[');
348 if (!bleft) {
349 break;
350 }
351 sscanf(bleft, "[%d]", &i);
352 countval *= i;
353 bleft2 = bleft;
354 }
355
356 delete[] countname;
357 countname = nullptr;
358 return nullptr;
359}
360
361////////////////////////////////////////////////////////////////////////////////
362/// If this branch is a branch count, return the set of collection size for
363/// the entry range requested
364/// start: first entry to read and return information about
365/// len: number of entries to read.
367{
368 if (len <= 0 || !IsRange())
369 return nullptr;
370
371 if (fLeafCountValues) {
373 {
374 return &fLeafCountValues->fValues;
375 }
376 if (start >= fLeafCountValues->fStartEntry &&
378 {
379 auto &values(fLeafCountValues->fValues);
380 values.erase(values.begin(), values.begin() + start-fLeafCountValues->fStartEntry);
381 return &values;
382 }
383 } else {
385 }
386
387
388 fLeafCountValues->fValues.clear();
389 fLeafCountValues->fValues.reserve(len);
391
392 auto branch = GetBranch();
393 Long64_t orig_leaf_entry = branch->GetReadEntry();
394 for (Long64_t idx = 0; idx < len; ++idx) {
395 branch->GetEntry(start + idx);
396 auto size = static_cast<Int_t>(GetValue());
397 fLeafCountValues->fValues.push_back( size );
398 }
399 branch->GetEntry(orig_leaf_entry);
400 return &(fLeafCountValues->fValues);
401}
402
403////////////////////////////////////////////////////////////////////////////////
404/// Return the number of effective elements of this leaf, for the current entry.
405
407{
408 if (fLeafCount) {
409 // -- We are a varying length array.
411 if (len > fLeafCount->GetMaximum()) {
412 Error("GetLen", "Leaf counter is greater than maximum! leaf: '%s' len: %d max: %d", GetName(), len, fLeafCount->GetMaximum());
414 }
415 return len * fLen;
416 } else {
417 // -- We are a fixed size thing.
418 return fLen;
419 }
420}
421
422////////////////////////////////////////////////////////////////////////////////
423/// Helper routine for TLeafX::SetAddress.
424///
425/// The return value is non-zero if we owned the old
426/// value buffer and must delete it now. The size
427/// of the value buffer is recalculated and stored,
428/// and a decision is made whether or not we own the
429/// new value buffer.
430
432{
433 // The kNewValue bit records whether or not we own
434 // the current value buffer or not. If we own it,
435 // then we are responsible for deleting it.
436 bool deleteValue = false;
437 if (TestBit(kNewValue)) {
438 deleteValue = true;
439 }
440 // If we are not being called from a destructor,
441 // recalculate the value buffer size and decide
442 // whether or not we own the new value buffer.
444 // -- Recalculate value buffer size and decide ownership of value.
445 if (fLeafCount) {
446 // -- Varying length array data member.
447 fNdata = (fLeafCount->GetMaximum() + 1) * fLen;
448 } else {
449 // -- Fixed size data member.
450 fNdata = fLen;
451 }
452 // If we were provided an address, then we do not own
453 // the value, otherwise we do and must delete it later,
454 // keep track of this with bit kNewValue.
455 if (addr) {
457 } else {
459 }
460 }
461 return deleteValue;
462}
463
464////////////////////////////////////////////////////////////////////////////////
465/// Set the leaf count of this leaf.
466
468{
469 if (IsZombie() && (fLen == -1) && leaf) {
470 // The constructor noted that it could not find the
471 // leafcount. Now that we did find it, let's remove
472 // the side-effects.
474 fLen = 1;
475 }
477}
478
479////////////////////////////////////////////////////////////////////////////////
480/// Stream a class object.
481
483{
484 if (b.IsReading()) {
486 Version_t R__v = b.ReadVersion(&R__s, &R__c);
487 if (R__v > 1) {
488 b.ReadClassBuffer(TLeaf::Class(), this, R__v, R__s, R__c);
489 } else {
490 // -- Process old versions before automatic schema evolution.
492 b >> fLen;
493 b >> fLenType;
494 b >> fOffset;
495 b >> fIsRange;
496 b >> fIsUnsigned;
497 b >> fLeafCount;
498 b.CheckByteCount(R__s, R__c, TLeaf::IsA());
499 }
500 if (!fLen) {
501 fLen = 1;
502 }
503 // We do not own the value buffer right now.
505 SetAddress();
506 } else {
507 b.WriteClassBuffer(TLeaf::Class(), this);
508 }
509}
510
#define R__unlikely(expr)
Definition RConfig.hxx:594
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
#define ClassImp(name)
Definition Rtypes.h:376
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
#define gPad
A TTree is a list of TBranches.
Definition TBranch.h:93
TTree * GetTree() const
Definition TBranch.h:252
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:2031
Long64_t GetReadEntry() const
Definition TBranch.h:237
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
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
Int_t fLenType
Number of bytes for this data type.
Definition TLeaf.h:73
bool fIsRange
(=true if leaf has a range, false otherwise). This is equivalent to being a 'leafcount'....
Definition TLeaf.h:75
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:366
virtual Int_t GetMaximum() const
Definition TLeaf.h:134
~TLeaf() override
Destructor.
Definition TLeaf.cxx:140
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:406
Int_t ResetAddress(void *add, bool calledFromDestructor=false)
Helper routine for TLeafX::SetAddress.
Definition TLeaf.cxx:431
TClass * IsA() const override
Definition TLeaf.h:168
void Streamer(TBuffer &) override
Stream a class object.
Definition TLeaf.cxx:482
TLeaf & operator=(const TLeaf &)
Assignment operator.
Definition TLeaf.cxx:117
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
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 SetAddress(void *add=nullptr)
Definition TLeaf.h:185
void Browse(TBrowser *b) override
Browse the content of this leaf.
Definition TLeaf.cxx:157
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
TBranch * fBranch
! Pointer to supporting branch (we do not own the branch)
Definition TLeaf.h:78
bool fIsUnsigned
(=true if unsigned, false otherwise)
Definition TLeaf.h:76
TLeaf * fLeafCount
Pointer to Leaf count if variable length (we do not own the counter)
Definition TLeaf.h:77
@ 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:467
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
static TClass * Class()
virtual bool IsRange() const
Definition TLeaf.h:149
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
void Streamer(TBuffer &) override
Stream an object of class TObject.
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition TNamed.cxx:51
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntries() const override
Return the number of objects in array (i.e.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
@ kZombie
object ctor failed
Definition TObject.h:89
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:159
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:865
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1072
void MakeZombie()
Definition TObject.h:53
void ResetBit(UInt_t f)
Definition TObject.h:201
Basic string class.
Definition TString.h:138
static constexpr Ssiz_t kNPOS
Definition TString.h:286
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:546
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:712
A TTree represents a columnar dataset.
Definition TTree.h:89
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:468
TCanvas * slash()
Definition slash.C:1
Long64_t fStartEntry
! entry number of corresponding to element 0 of the vector.
Definition TLeaf.h:68