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