Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTreeReaderValue.h
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Axel Naumann, 2010-08-02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, 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 #ifndef ROOT_TTreeReaderValue
13 #define ROOT_TTreeReaderValue
14 
15 ////////////////////////////////////////////////////////////////////////////
16 // //
17 // TTreeReaderValue //
18 // //
19 // A simple interface for reading data from trees or chains. //
20 // //
21 // //
22 ////////////////////////////////////////////////////////////////////////////
23 
24 #include "TString.h"
25 #include "TDictionary.h"
26 #include "TBranchProxy.h"
27 
28 #include <type_traits>
29 
30 class TBranch;
31 class TBranchElement;
32 class TLeaf;
33 class TTreeReader;
34 
35 namespace ROOT {
36 namespace Internal {
37 
38 /** \class TTreeReaderValueBase
39 Base class of TTreeReaderValue.
40 */
41 
42  class TTreeReaderValueBase {
43  public:
44 
45  // Status flags, 0 is good
46  enum ESetupStatus {
47  kSetupNotSetup = -7, /// No initialization has happened yet.
48  kSetupTreeDestructed = -8, /// The TTreeReader has been destructed / not set.
49  kSetupMakeClassModeMismatch = -7, // readers disagree on whether TTree::SetMakeBranch() should be on
50  kSetupMissingCounterBranch = -6, /// The array cannot find its counter branch: Array[CounterBranch]
51  kSetupMissingBranch = -5, /// The specified branch cannot be found.
52  kSetupInternalError = -4, /// Some other error - hopefully the error message helps.
53  kSetupMissingDictionary = -3, /// To read this branch, we need a dictionary.
54  kSetupMismatch = -2, /// Mismatch of branch type and reader template type.
55  kSetupNotACollection = -1, /// The branch class type is not a collection.
56  kSetupMatch = 0, /// This branch has been set up, branch data type and reader template type match, reading should succeed.
57  kSetupMatchBranch = 0, /// This branch has been set up, branch data type and reader template type match, reading should succeed.
58  //kSetupMatchConversion = 1, /// This branch has been set up, the branch data type can be converted to the reader template type, reading should succeed.
59  //kSetupMatchConversionCollection = 2, /// This branch has been set up, the data type of the branch's collection elements can be converted to the reader template type, reading should succeed.
60  //kSetupMakeClass = 3, /// This branch has been set up, enabling MakeClass mode for it, reading should succeed.
61  // kSetupVoidPtr = 4,
62  kSetupNoCheck = 5,
63  kSetupMatchLeaf = 6 /// This branch (or TLeaf, really) has been set up, reading should succeed.
64  };
65  enum EReadStatus {
66  kReadSuccess = 0, // data read okay
67  kReadNothingYet, // data now yet accessed
68  kReadError // problem reading data
69  };
70 
71  EReadStatus ProxyRead() { return (this->*fProxyReadFunc)(); }
72 
73  EReadStatus ProxyReadDefaultImpl();
74 
75  typedef Bool_t (ROOT::Detail::TBranchProxy::*BranchProxyRead_t)();
76  template <BranchProxyRead_t Func>
77  ROOT::Internal::TTreeReaderValueBase::EReadStatus ProxyReadTemplate();
78 
79  Bool_t IsValid() const { return fProxy && 0 == (int)fSetupStatus && 0 == (int)fReadStatus; }
80  ESetupStatus GetSetupStatus() const { return fSetupStatus; }
81  virtual EReadStatus GetReadStatus() const { return fReadStatus; }
82 
83  /// If we are reading a leaf, return the corresponding TLeaf.
84  TLeaf* GetLeaf() { return fLeaf; }
85 
86  void* GetAddress();
87 
88  const char* GetBranchName() const { return fBranchName; }
89 
90  virtual ~TTreeReaderValueBase();
91 
92  protected:
93  TTreeReaderValueBase(TTreeReader* reader, const char* branchname, TDictionary* dict);
94  TTreeReaderValueBase(const TTreeReaderValueBase&);
95  TTreeReaderValueBase& operator=(const TTreeReaderValueBase&);
96 
97  void RegisterWithTreeReader();
98  void NotifyNewTree(TTree* newTree);
99 
100  TBranch* SearchBranchWithCompositeName(TLeaf *&myleaf, TDictionary *&branchActualType, std::string &err);
101  virtual void CreateProxy();
102  static const char* GetBranchDataType(TBranch* branch,
103  TDictionary* &dict,
104  TDictionary const *curDict);
105 
106  virtual const char* GetDerivedTypeName() const = 0;
107 
108  Detail::TBranchProxy* GetProxy() const { return fProxy; }
109 
110  void MarkTreeReaderUnavailable() { fTreeReader = 0; fSetupStatus = kSetupTreeDestructed; }
111 
112  /// Stringify the template argument.
113  static std::string GetElementTypeName(const std::type_info& ti);
114 
115  int fHaveLeaf : 1; // Whether the data is in a leaf
116  int fHaveStaticClassOffsets : 1; // Whether !fStaticClassOffsets.empty()
117  EReadStatus fReadStatus : 2; // read status of this data access
118  ESetupStatus fSetupStatus = kSetupNotSetup; // setup status of this data access
119  TString fBranchName; // name of the branch to read data from.
120  TString fLeafName;
121  TTreeReader* fTreeReader; // tree reader we belong to
122  TDictionary* fDict; // type that the branch should contain
123  Detail::TBranchProxy* fProxy = nullptr; // proxy for this branch, owned by TTreeReader
124  TLeaf* fLeaf = nullptr;
125  std::vector<Long64_t> fStaticClassOffsets;
126  typedef EReadStatus (TTreeReaderValueBase::*Read_t)();
127  Read_t fProxyReadFunc = &TTreeReaderValueBase::ProxyReadDefaultImpl; ///<! Pointer to the Read implementation to use.
128 
129  // FIXME: re-introduce once we have ClassDefInline!
130  //ClassDef(TTreeReaderValueBase, 0);//Base class for accessors to data via TTreeReader
131 
132  friend class ::TTreeReader;
133  };
134 
135 } // namespace Internal
136 } // namespace ROOT
137 
138 
139 template <typename T>
140 class R__CLING_PTRCHECK(off) TTreeReaderValue final: public ROOT::Internal::TTreeReaderValueBase {
141 // R__CLING_PTRCHECK is disabled because pointer / types are checked by CreateProxy().
142 
143 public:
144  using NonConstT_t = typename std::remove_const<T>::type;
145  TTreeReaderValue() = delete;
146  TTreeReaderValue(TTreeReader& tr, const char* branchname):
147  TTreeReaderValueBase(&tr, branchname,
148  TDictionary::GetDictionary(typeid(NonConstT_t))) {}
149 
150  /// Return a pointer to the value of the current entry.
151  /// Return a nullptr and print an error if no entry has been loaded yet.
152  /// The returned address is guaranteed to stay constant while a given TTree is being read from a given file,
153  /// unless the branch addresses are manipulated directly (e.g. through TTree::SetBranchAddress()).
154  /// The address might also change when the underlying TTree/TFile is switched, e.g. when a TChain switches files.
155  T* Get() {
156  if (!fProxy){
157  Error("TTreeReaderValue::Get()", "Value reader not properly initialized, did you remember to call TTreeReader.Set(Next)Entry()?");
158  return nullptr;
159  }
160  void *address = GetAddress(); // Needed to figure out if it's a pointer
161  return fProxy->IsaPointer() ? *(T**)address : (T*)address; }
162  /// Return a pointer to the value of the current entry.
163  /// Equivalent to Get().
164  T* operator->() { return Get(); }
165  /// Return a reference to the value of the current entry.
166  /// Equivalent to dereferencing the pointer returned by Get(). Behavior is undefined if no entry has been loaded yet.
167  /// Most likely a crash will occur.
168  T& operator*() { return *Get(); }
169 
170 protected:
171  // FIXME: use IsA() instead once we have ClassDefTInline
172  /// Get the template argument as a string.
173  virtual const char* GetDerivedTypeName() const {
174  static const std::string sElementTypeName = GetElementTypeName(typeid(T));
175  return sElementTypeName.data();
176  }
177 
178  // FIXME: re-introduce once we have ClassDefTInline!
179  //ClassDefT(TTreeReaderValue, 0);//Accessor to data via TTreeReader
180 };
181 
182 #endif // ROOT_TTreeReaderValue