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