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, '[');
93 if (bracket) fName.ReplaceAll(bracket,"");
94}
95
96////////////////////////////////////////////////////////////////////////////////
97/// Copy constructor.
98
99TLeaf::TLeaf(const TLeaf& lf) :
100 TNamed(lf),
101 fNdata(lf.fNdata),
102 fLen(lf.fLen),
103 fLenType(lf.fLenType),
104 fOffset(lf.fOffset),
105 fIsRange(lf.fIsRange),
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;
123 fOffset=lf.fOffset;
127 fBranch=lf.fBranch;
128 if (fLeafCountValues) {
129 fLeafCountValues->fStartEntry = -1;
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)) {
163 TString name(fBranch->GetName());
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{
225 TString branchname = GetBranch()->GetFullName();
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
252 TString sname = (slash == TString::kNPOS) ? fTitle : TString(fTitle(0, slash));
253 const char *name = sname.Data();
254 char* bleft = (char*) strchr(name, '[');
255 if (!bleft) {
256 return nullptr;
257 }
258 bleft++;
259 Int_t nch = strlen(bleft);
260 char* countname = new char[nch+1];
261 strlcpy(countname, bleft, 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;
271 nch = strlen(countname);
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 }
284 TTree* pTree = fBranch->GetTree();
285
286 TLeaf* leaf = (TLeaf*) GetBranch()->GetListOfLeaves()->FindObject(countname);
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];
294 strcpy(withdot, GetName());
295 char* lastdot = strrchr(withdot, '.');
296 strcpy(lastdot, countname);
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) {
371 if (fLeafCountValues->fStartEntry == start && len < (Long64_t)fLeafCountValues->fValues.size())
372 {
373 return &fLeafCountValues->fValues;
374 }
375 if (start >= fLeafCountValues->fStartEntry &&
376 (start+len) <= (Long64_t)(fLeafCountValues->fStartEntry + fLeafCountValues->fValues.size()))
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);
389 fLeafCountValues->fStartEntry = start;
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.
409 Int_t len = Int_t(fLeafCount->GetValue());
410 if (len > fLeafCount->GetMaximum()) {
411 Error("GetLen", "Leaf counter is greater than maximum! leaf: '%s' len: %d max: %d", GetName(), len, fLeafCount->GetMaximum());
412 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
430Int_t TLeaf::ResetAddress(void* addr, bool calledFromDestructor)
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.
442 if (!calledFromDestructor) {
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 }
475 fLeafCount = leaf;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Stream a class object.
480
482{
483 if (b.IsReading()) {
484 UInt_t R__s, R__c;
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:586
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
start
Definition Rotated.cxx:223
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
short Version_t
Class version identifier (short).
Definition RtypesCore.h:79
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int).
Definition RtypesCore.h:60
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
char name[80]
Definition TGX11.cxx:148
#define gPad
A TTree is a list of TBranches.
Definition TBranch.h:93
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:2030
TObjArray * GetListOfLeaves()
Definition TBranch.h:256
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Double_t GetValue(Int_t i=0) const
Definition TLeaf.h:186
TLeaf(const TLeaf &)
Copy constructor.
Definition TLeaf.cxx:99
Int_t fLenType
Number of bytes for this data type.
Definition TLeaf.h:76
bool fIsRange
(=true if leaf has a range, false otherwise). This is equivalent to being a 'leafcount'....
Definition TLeaf.h:78
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
~TLeaf() override
Destructor.
Definition TLeaf.cxx:139
Int_t fLen
Number of fixed length elements in the leaf's data.
Definition TLeaf.h:75
Int_t fNdata
! Number of elements in fAddress data buffer.
Definition TLeaf.h:74
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:171
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:188
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:119
Int_t fOffset
Offset in ClonesArray object (if one).
Definition TLeaf.h:77
virtual Int_t GetOffsetHeaderSize() const
Definition TLeaf.h:61
TBranch * fBranch
! Pointer to supporting branch (we do not own the branch)
Definition TLeaf.h:81
bool fIsUnsigned
(=true if unsigned, false otherwise)
Definition TLeaf.h:79
TLeaf * fLeafCount
Pointer to Leaf count if variable length (we do not own the counter).
Definition TLeaf.h:80
@ kNewValue
Set if we own the value buffer and so must delete it ourselves.
Definition TLeaf.h:99
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:82
virtual void SetRange(bool range=true)
Definition TLeaf.h:168
std::vector< Int_t > Counts_t
Definition TLeaf.h:65
static TClass * Class()
virtual bool IsRange() const
Definition TLeaf.h:152
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
TNamed()
Definition TNamed.h:38
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
TObject * Remove(TObject *obj) override
Remove object from array.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
Int_t GetLast() const override
Return index of last object in array.
Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
@ kZombie
object ctor failed
Definition TObject.h:92
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
void MakeZombie()
Definition TObject.h:55
Bool_t IsZombie() const
Definition TObject.h:161
void ResetBit(UInt_t f)
Definition TObject.h:203
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:425
static constexpr Ssiz_t kNPOS
Definition TString.h:286
const char * Data() const
Definition TString.h:384
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:576
virtual TLeaf * FindLeaf(const char *name)
Find first leaf containing searchname.
Definition TTree.cxx:4965
TCanvas * slash()
Definition slash.C:1