BasicTypesProxy.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <array>
4 #include <cassert>
5 #include <set>
6 #include <string>
7 #include <vector>
8 
9 class TDirectory;
10 class TFormLeafInfo;
11 class TBranch;
12 class TLeaf;
13 class TTreeFormula;
14 class TTree;
15 
16 namespace caf
17 {
19  {
20  public:
21  static void AddBranch(const std::string& b){fgBranches.insert(b);}
22  static const std::set<std::string>& GetBranches(){return fgBranches;}
23  static void clear() {fgBranches.clear();}
24 
25  static void Print(bool abbrev = true);
26  static void ToFile(const std::string& fname);
27  protected:
28  static std::set<std::string> fgBranches;
29  };
30 
31  enum CAFType
32  {
36  kCopiedRecord // Assigned into, not associated with a file
37  };
38 
39  CAFType GetCAFType(const TDirectory* dir, TTree* tr);
40 
41  /// Count the subscripts in the name
42  int NSubscripts(const std::string& name);
43 
44  template<class T> class Proxy;
45 
46  class Restorer;
47 
48  template<class T> class Proxy
49  {
50  public:
51  static_assert(std::is_arithmetic_v<T> || std::is_enum_v<T> || std::is_same_v<T, std::string>, "Invalid type for basic type Proxy");
52 
53  friend class Restorer;
54 
55  Proxy(TDirectory* d, TTree* tr, const std::string& name, const long& base, int offset);
56 
57  // Need to be copyable because Vars return us directly
58  Proxy(const Proxy&);
59  Proxy(const Proxy&&);
60  // No need to be assignable though
61  Proxy& operator=(const Proxy&) = delete;
62 
63  // Somehow including this helps us not get automatically converted to a
64  // type we might not want to be in ternary expressions (we now get a type
65  // error instead).
66  Proxy(T v) = delete;
67 
68  ~Proxy();
69 
70  operator T() const {return GetValue();}
71 
72  T GetValue() const;
73 
74  // In practice these are the only operations that systematic shifts use
75  Proxy<T>& operator=(T x);
76  Proxy<T>& operator+=(T x);
77  Proxy<T>& operator*=(T x);
78 
79  std::string Name() const {return fName;}
80 
81  void CheckEquals(const T& x) const;
82 
83  protected:
84  T GetValueNested() const;
85  T GetValueFlatSingle() const;
86  T GetValueFlatMulti() const;
87 
88  void SetShifted();
89 
90  // The type to fetch from the TLeaf - get template errors inside of ROOT
91  // for enums.
92  typedef typename std::conditional_t<std::is_enum_v<T>, int, T> U;
93 
94  // Shared
97  mutable TLeaf* fLeaf;
98  mutable U fVal;
99  TTree* fTree;
100 
101  // Flat
102  TDirectory* fDir;
103  const long& fBase;
104  int fOffset;
105 
106  // Nested
107  mutable TFormLeafInfo* fLeafInfo;
108  mutable TBranch* fBranch;
109  mutable TTreeFormula* fTTF;
110  mutable long fEntry;
111  mutable int fSubIdx;
112  };
113 
114  // Helper functions that don't need to be templated
116  {
117  public:
118  std::string Name() const {return fName;}
119 
120  protected:
121  ArrayVectorProxyBase(TDirectory* d, TTree* tr, const std::string& name,
122  const long& base, int offset);
123 
125 
126  void CheckIndex(size_t i, size_t size) const;
127  TTree* GetTreeForName() const;
128 
129  std::string IndexField() const;
130 
131  /// add [i], or something more complex for nested CAFs
132  std::string Subscript(int i) const;
133 
134  TDirectory* fDir;
135  TTree* fTree;
138  const long& fBase;
139  int fOffset;
141  mutable long fIdx;
142  };
143 
144  // Helper functions that don't need to be templated
146  {
147  public:
148  size_t size() const;
149  bool empty() const;
150  void resize(size_t i);
151 
152  protected:
153  VectorProxyBase(TDirectory* d, TTree* tr, const std::string& name, const long& base, int offset);
154 
155  std::string LengthField() const;
156  /// Helper for LengthField()
157  std::string NName() const;
158 
160 
161  mutable bool fWarn;
162  };
163 
164  template<class T> class Proxy<std::vector<T>>: public VectorProxyBase
165  {
166  public:
167  Proxy(TDirectory* d, TTree* tr, const std::string& name, const long& base, int offset)
168  : VectorProxyBase(d, tr, name, base, offset)
169  {
170  }
171 
172  ~Proxy(){for(Proxy<T>* e: fElems) delete e;}
173 
174  Proxy& operator=(const Proxy<std::vector<T>>&) = delete;
175  Proxy(const Proxy<std::vector<T>>& v) = delete;
176 
177  Proxy<T>& at(size_t i) const {EnsureSize(i); return *fElems[i];}
178  Proxy<T>& at(size_t i) {EnsureSize(i); return *fElems[i];}
179 
180  Proxy<T>& operator[](size_t i) const {return at(i);}
181  Proxy<T>& operator[](size_t i) {return at(i);}
182 
183  template<class U> Proxy<std::vector<T>>& operator=(const std::vector<U>& x)
184  {
185  resize(x.size());
186  for(unsigned int i = 0; i < x.size(); ++i) at(i) = x[i];
187  return *this;
188  }
189 
190  template<class U>
191  void CheckEquals(const std::vector<U>& x) const
192  {
193  fSize.CheckEquals(x.size());
194  for(unsigned int i = 0; i < std::min(size(), x.size()); ++i) at(i).CheckEquals(x[i]);
195  }
196 
197 
198  // U should be either T or const T
199  template<class U> class iterator
200  {
201  public:
202  Proxy<T>& operator*() {return (*fParent)[fIdx];}
203  iterator<U>& operator++(){++fIdx; return *this;}
204  bool operator!=(const iterator<U>& it) const {return fIdx != it.fIdx;}
205  bool operator==(const iterator<U>& it) const {return fIdx == it.fIdx;}
206  protected:
207  friend class Proxy<std::vector<T>>;
208  iterator(const Proxy<std::vector<T>>* p, int i) : fParent(p), fIdx(i) {}
209 
211  size_t fIdx;
212  };
213 
214  iterator<const T> begin() const {return iterator<const T>(this, 0 );}
215  iterator< T> begin() {return iterator< T>(this, 0 );}
216  iterator<const T> end() const {return iterator<const T>(this, size());}
217  iterator< T> end() {return iterator< T>(this, size());}
218 
219  protected:
220  /// Implies CheckIndex()
221  void EnsureSize(size_t i) const
222  {
223  CheckIndex(i, size());
224  if(i >= fElems.size()) fElems.resize(i+1);
225 
226  if(fIdxP) fIdx = *fIdxP; // store into an actual value we can point to
227 
228  if(!fElems[i]) fElems[i] = new Proxy<T>(fDir, GetTreeForName(), Subscript(i), fIdx, i);
229  }
230 
231  mutable std::vector<Proxy<T>*> fElems;
232  };
233 
234  // Retain an alias to the old naming scheme for now
235  template <class T> using VectorProxy = Proxy<std::vector<T>>;
236 
237 
238  /// Used in comparison of GENIE version numbers
239  template<class T> bool operator<(const Proxy<std::vector<T>>& a,
240  const std::vector<T>& b)
241  {
242  const size_t N = a.size();
243  if(N != b.size()) return N < b.size();
244  for(size_t i = 0; i < N; ++i){
245  if(a[i] != b[i]) return a[i] < b[i];
246  }
247  return false;
248  }
249 
250  template<class T, unsigned int N> class Proxy<T[N]> : public ArrayVectorProxyBase
251  {
252  public:
253  Proxy(TDirectory* d, TTree* tr, const std::string& name, const long& base, int offset)
254  : ArrayVectorProxyBase(d, tr, name, base, offset)
255  {
256  }
257 
259  {
260  for(Proxy<T>* e: fElems) delete e;
261  }
262 
263  Proxy& operator=(const Proxy<T[N]>&) = delete;
264  Proxy(const Proxy<T[N]>& v) = delete;
265 
266  const Proxy<T>& operator[](size_t i) const
267  {
268  EnsureElem(i);
269  if(fIdxP) fIdx = *fIdxP;
270  return *fElems[i];
271  }
273  {
274  EnsureElem(i);
275  if(fIdxP) fIdx = *fIdxP;
276  return *fElems[i];
277  }
278 
279  Proxy<T[N]>& operator=(const T (&x)[N])
280  {
281  for(unsigned int i = 0; i < N; ++i) (*this)[i] = x[i];
282  return *this;
283  }
284 
285  void CheckEquals(const T (&x)[N]) const
286  {
287  for(unsigned int i = 0; i < N; ++i) (*this)[i].CheckEquals(x[i]);
288  }
289 
290  protected:
291  void EnsureElem(int i) const
292  {
293  CheckIndex(i, N);
294  if(!fElems[i]) fElems[i] = new Proxy<T>(fDir, fTree, Subscript(i), fIdx, i);
295  }
296 
297  mutable std::array<Proxy<T>*, N> fElems;
298  };
299 
300  // Retain an alias to the old naming scheme for now
301  template <class T, unsigned int N> using ArrayProxy = Proxy<T[N]>;
302 
303 
304  template<class T> class RestorerT
305  {
306  public:
308  {
309  // Restore values in reverse, i.e. in first-in, last-out order so that if
310  // a value was edited multiple time it will eventually be restored to its
311  // original value.
312  for(auto it = fVals.rbegin(); it != fVals.rend(); ++it)
313  *it->first = it->second;
314  }
315 
316  void Add(T* p, T v)
317  {
318  fVals.emplace_back(p, v);
319  }
320 
321  protected:
322  std::vector<std::pair<T*, T>> fVals;
323  };
324 
325  class Restorer: public
326  RestorerT<char>,
327  RestorerT<short>,
328  RestorerT<int>,
329  RestorerT<long>,
330  RestorerT<long long>,
331  RestorerT<unsigned char>,
332  RestorerT<unsigned short>,
333  RestorerT<unsigned int>,
334  RestorerT<unsigned long>,
335  RestorerT<unsigned long long>,
336  RestorerT<float>,
337  RestorerT<double>,
338  RestorerT<long double>,
339  RestorerT<bool>,
340  RestorerT<std::string>
341  {
342  public:
343  template<class T> void Add(Proxy<T>& p)
344  {
346  }
347  };
348 
350  {
351  public:
352  static bool AnyShifted()
353  {
354  for(const Restorer* r: fRestorers) if(r) return true;
355  return false;
356  }
357 
358  static void BeginTransaction()
359  {
360  fRestorers.push_back(0);
361  }
362 
363  static bool InTransaction()
364  {
365  return !fRestorers.empty();
366  }
367 
368  static void Rollback()
369  {
370  assert(!fRestorers.empty());
371  if(fRestorers.back()) ++fGeneration;
372  delete fRestorers.back();
373  fRestorers.pop_back();
374  }
375 
376  /// May be useful in the implementation of caches that ought to be
377  /// invalidated when systematic shifts are applied.
378  static long long Generation()
379  {
380  if(!InTransaction()) return 0; // nominal
381  return fGeneration;
382  }
383 
384  protected:
385  template<class T> friend class Proxy;
386 
387  template<class T> static void Backup(Proxy<T>& p)
388  {
389  assert(!fRestorers.empty());
390  if(!fRestorers.back()){
391  ++fGeneration;
392  fRestorers.back() = new Restorer;
393  }
394  fRestorers.back()->Add(p);
395  }
396 
397  static std::vector<Restorer*> fRestorers;
398  static long long fGeneration;
399  };
400 
401 } // namespace
402 
403 namespace std
404 {
405  template<class T> T min(const caf::Proxy<T>& a, T b)
406  {
407  return std::min(a.GetValue(), b);
408  }
409 
410  template<class T> T min(T a, const caf::Proxy<T>& b)
411  {
412  return std::min(a, b.GetValue());
413  }
414 
415  template<class T> T max(const caf::Proxy<T>& a, T b)
416  {
417  return std::max(a.GetValue(), b);
418  }
419 
420  template<class T> T max(T a, const caf::Proxy<T>& b)
421  {
422  return std::max(a, b.GetValue());
423  }
424 }
Proxy< T > & at(size_t i) const
T max(const caf::Proxy< T > &a, T b)
const XML_Char * name
Definition: expat.h:151
static void ToFile(const std::string &fname)
Proxy< long long > * fIdxP
TDC::value_type operator+=(TDC lhs, TDC rhs)
Definition: BaseProducts.h:53
set< int >::iterator it
static std::set< std::string > fgBranches
TDirectory * fDir
CAFType fType
T GetValue() const
const char * p
Definition: xmltok.h:285
Proxy(TDirectory *d, TTree *tr, const std::string &name, const long &base, int offset)
Proxy< T > & operator[](size_t i)
Proxy< std::vector< T > > & operator=(const std::vector< U > &x)
static void Backup(Proxy< T > &p)
void EnsureSize(size_t i) const
Implies CheckIndex()
bool operator!=(const iterator< U > &it) const
std::string fName
Proxy< T[N]> & operator=(const T(&x)[N])
const Proxy< std::vector< T > > * fParent
Proxy< T > & operator[](size_t i) const
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
std::string Name() const
std::vector< std::pair< T *, T > > fVals
void Add(T *p, T v)
CAFType GetCAFType(const TDirectory *dir, TTree *tr)
TFormLeafInfo * fLeafInfo
std::vector< Proxy< T > * > fElems
static void Print(bool abbrev=true)
void Add(Proxy< T > &p)
static long long Generation()
const double a
int NSubscripts(const std::string &name)
Count the subscripts in the name.
void resize(T &x, std::vector< int > dims)
Definition: resize.hpp:41
Proxy(TDirectory *d, TTree *tr, const std::string &name, const long &base, int offset)
std::string Name() const
const long & fBase
TLeaf * fLeaf
bool operator==(const iterator< U > &it) const
Float_t d
Definition: plot.C:236
std::conditional_t< std::is_enum_v< T >, int, T > U
TTreeFormula * fTTF
void CheckEquals(const std::vector< U > &x) const
static float min(const float a, const float b, const float c)
Definition: absgeo.cxx:45
static const std::set< std::string > & GetBranches()
TDirectory * dir
Definition: macro.C:5
void EnsureElem(int i) const
const hit & b
Definition: hits.cxx:21
assert(nhit_max >=nhit_nbins)
TRandom3 r(0)
Proxy< T > & operator[](size_t i)
static void AddBranch(const std::string &b)
static std::vector< Restorer * > fRestorers
double T
Definition: Xdiff_gwt.C:5
This module creates Common Analysis Files.
Definition: FileReducer.h:10
T min(const caf::Proxy< T > &a, T b)
Float_t e
Definition: plot.C:35
const Proxy< T > & operator[](size_t i) const
TTree * fTree
Proxy< T > & at(size_t i)
static long long fGeneration
std::array< Proxy< T > *, N > fElems
void CheckEquals(const T(&x)[N]) const
iterator< const T > end() const
iterator< const T > begin() const
T max(T a, const caf::Proxy< T > &b)
TBranch * fBranch
enum BeamMode string