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