intermediate_table.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_intermediate_table_h
2 #define fhiclcpp_intermediate_table_h
3 
4 ////////////////////////////////////////////////////////////////////////
5 // intermediate table: generic representation of parameters.
6 //
7 // This class should only be used in the following two circumstances:
8 //
9 // 1. Configuration post-processing, prior to ParameterSet creation
10 // (use the "simple interface" where possible).
11 //
12 // 2. Internally by FHiCL.
13 //
14 // In all other circumstances, ParameterSet is almost certainly more
15 // appropriate.
16 //
17 // 2012/08/29 CG.
18 ////////////////////////////////////////////////////////////////////////
19 
20 ////////////////////////////////////////////////////////////////////////
21 // Supplemental expert notes on intermediate_table vs ParameterSet.
22 //
23 // 1. Intermediate tables contain only extended values; ParameterSets
24 // contain only boost::any.
25 //
26 // 2. The boost::any in a ParameterSet may not be the same type as the
27 // boost::any in the corresponding extended_value in the intermediate
28 // table whence it came.
29 //
30 // 3. An extended_value::sequence_t is std::vector<extended_value>; a
31 // ParameterSet::ps_sequence_t is std::vector<boost::any>.
32 //
33 // 4. An extended_value::table_t is std::map<std::string,
34 // extended_value>; the equivalent concept in ParameterSet is
35 // ParameterSet (stored as boost::any).
36 //
37 // 5. An extended_value::complex_t is std::pair<std::string,
38 // std::string>; the equivalent concept in ParameterSet is
39 // std::string (stored as boost::any).
40 //
41 // 6. Numbers, boolean values and strings are to be stored in
42 // intermediate_tables at all times in their canonical string form
43 // (using detail::encode()); complex numbers are stored in
44 // intermediate tables as a pair of strings representing the
45 // canonical string forms of the real and imaginary parts. In
46 // ParameterSets they are stored as a single std::string,
47 // "(real,imag)".
48 //
49 ////////////////////////////////////////////////////////////////////////
50 
51 #include "boost/any.hpp"
52 #include "fhiclcpp/coding.h"
54 #include "fhiclcpp/fwd.h"
55 #include "fhiclcpp/type_traits.h"
56 
57 #include <complex>
58 #include <map>
59 #include <string>
60 #include <vector>
61 
62 // ----------------------------------------------------------------------
63 
65 public:
66  // Constructor
68 
69  ////////////////////
70  // Simple interface:
71  bool empty() const;
72 
73  bool exists(std::string const& name) const;
74 
75  void erase(std::string const& name, bool in_prolog = false);
76 
77  template <typename T>
78  T get(std::string const& name);
79 
80  bool put(std::string const& name,
81  std::string const& value, // String.
82  bool in_prolog = false);
83  bool put(std::string const& name,
84  char const* value, // String.
85  bool in_prolog = false);
86  bool put(std::string const& name,
87  bool value, // Boolean.
88  bool in_prolog = false);
89  template <typename T>
90  bool put(std::string const& name,
91  std::complex<T> const& value, // Complex.
92  bool in_prolog = false);
93  template <typename T>
94  bool put(std::string const& name,
95  std::vector<T> const& value, // Sequence.
96  bool in_prolog = false);
97  template <typename T>
99  std::string const& name,
100  T value, // Number
101  bool in_prolog = false);
102 
103  bool putEmptySequence(std::string const& name,
104  bool in_prolog = false); // Empty Sequence.
105  bool putEmptyTable(std::string const& name,
106  bool in_prolog = false); // Empty Table.
107  bool putNil(std::string const& name,
108  bool in_prolog = false); // Nil.
109 
110  ////////////////////
111  // Expert interface.
112  // Typedefs.
119 
120  const_iterator begin() const;
121  const_iterator end() const;
122 
123  // Flexible insert interface.
124  bool insert(std::string const& name,
125  bool in_prolog,
126  value_tag tag,
127  boost::any const& value);
128  bool insert(std::string const& name, extended_value const& value);
129  bool insert(std::string const& name, extended_value&& value);
130 
131  /// \throw if item does not exist.
132  extended_value const& find(std::string const& name) const;
133 
134  /// \return nullptr if not able to be updated.
135  extended_value* locate(std::string const& name);
136 
137  /// \throw if not able to be updated.
138  extended_value& update(std::string const& name);
139 
140 private:
141  // Do all the work required to find somewhere to put the new
142  // value. Called by insert().
144  extended_value const& value);
145 
146  // Return an item with a bool indicating whether it may be updated.
147  std::pair<extended_value*, bool> locate_(std::string const& name,
148  bool in_prolog = false);
149 
150  std::vector<std::string> split(std::string const& name) const;
151 
153 
154 }; // intermediate_table
155 
156 namespace fhicl {
157  namespace detail {
158 
159  // Template declaration (no general definition).
160  template <typename T, typename Enable = void>
162 
163  // Partial specialization for value types.
164  template <typename T>
166  T,
167  typename tt::disable_if<std::is_reference<T>::value ||
168  std::is_pointer<T>::value>::type> {
169  public:
170  T
172  {
173  T result;
174  detail::decode(table.find(name).value, result);
175  return result;
176  }
177  };
178 
179  // Partial specialization for std::complex<U>.
180  template <typename U>
182  std::complex<U>,
183  typename tt::disable_if<std::is_reference<std::complex<U>>::value ||
184  std::is_pointer<std::complex<U>>::value>::type> {
185  public:
186  std::complex<U>
188  {
189  intermediate_table::complex_t c(table.find(name));
190  U r, i;
191  detail::decode(c.first, r);
192  detail::decode(c.second, i);
193  return std::complex<U>(r, i);
194  }
195  };
196 
197  // Full specialization for sequence_t
198  template <>
200  public:
203  {
204  return boost::any_cast<intermediate_table::sequence_t>(
205  table.find(name).value);
206  }
207  };
208 
209  // Full specialization for sequence_t &: will throw if not writable
210  template <>
212  public:
213  intermediate_table::sequence_t&
215  {
216  auto item = sequence.locate(name);
217  if (item != nullptr) {
218  return boost::any_cast<intermediate_table::sequence_t&>(item->value);
219  } else {
221  << "Requested non-updatable parameter \"" << name
222  << "\" for update.\n";
223  }
224  }
225  };
226 
227  // Full specialization for sequence_t const &
228  template <>
230  public:
231  intermediate_table::sequence_t const&
233  {
234  return boost::any_cast<intermediate_table::sequence_t const&>(
235  table.find(name).value);
236  }
237  };
238 
239  // Full specialization for table_t
240  template <>
242  public:
245  {
246  return boost::any_cast<intermediate_table::table_t>(
247  table.find(name).value);
248  }
249  };
250 
251  // Full specialization for table_t &: will throw if not writable
252  template <>
254  public:
255  intermediate_table::table_t&
257  {
258  auto item = table.locate(name);
259  if (item != nullptr) {
260  return boost::any_cast<intermediate_table::table_t&>(item->value);
261  } else {
263  << "Requested non-updatable parameter " << name << " for update.\n";
264  }
265  }
266  };
267 
268  // Full specialization for table_t const &
269  template <>
271  public:
272  intermediate_table::table_t const&
274  {
275  return boost::any_cast<intermediate_table::table_t const&>(
276  table.find(name).value);
277  }
278  };
279  }
280 }
281 
282 template <typename T>
283 inline T
285 {
286  static detail::it_value_get<T> getter;
287  return getter(*this, name);
288 }
289 
290 inline bool
292  std::string const& value, // String.
293  bool in_prolog)
294 {
295  return insert(name, in_prolog, STRING, detail::encode(value));
296 }
297 
298 inline bool
300  char const* value, // String.
301  bool in_prolog)
302 {
303  return insert(name, in_prolog, STRING, detail::encode(value));
304 }
305 
306 inline bool
308  bool value, // Boolean.
309  bool in_prolog)
310 {
311  return insert(name, in_prolog, BOOL, detail::encode(value));
312 }
313 
314 template <typename T>
315 bool
317  std::complex<T> const& value, // Complex.
318  bool in_prolog)
319 {
320  return insert(
321  name,
322  in_prolog,
323  COMPLEX,
324  complex_t(detail::encode(value.real()), detail::encode(value.imag())));
325 }
326 
327 template <typename T>
328 inline bool
330  std::vector<T> const& value, // Sequence.
331  bool in_prolog)
332 {
333  bool result = putEmptySequence(name, in_prolog);
334  if (!result) {
335  return result;
336  }
337  size_t count(0);
338  for (auto const& item : value) {
339  result = result &&
340  put(name + "[" + std::to_string(count++) + "]", item, in_prolog);
341  }
342  return result;
343 }
344 
345 template <typename T>
348  T value, // Number
349  bool in_prolog)
350 {
351  return insert(name, in_prolog, NUMBER, detail::encode(value));
352 }
353 
355  std::string const& name,
356  bool in_prolog) // Sequence.
357 {
358  return insert(name, in_prolog, SEQUENCE, sequence_t());
359 }
360 
362  bool in_prolog) // Table.
363 {
364  return insert(name, in_prolog, TABLE, table_t());
365 }
366 
368  bool in_prolog) // Nil.
369 {
370  return insert(name, in_prolog, NIL, detail::encode((void*)0));
371 }
372 
373 inline fhicl::extended_value*
375 {
376  extended_value* result = nullptr;
377  auto located = locate_(name);
378  if (located.second) {
379  result = located.first;
380  }
381  return result;
382 }
383 
384 inline fhicl::extended_value&
386 {
387  auto located = locate_(name);
388  if (!located.second) {
390  << "Requested non-modifiable item \"" << name << "\" for update.\n";
391  }
392  return *located.first;
393 }
394 
395 #endif /* fhiclcpp_intermediate_table_h */
396 
397 // Local Variables:
398 // mode: c++
399 // End:
const XML_Char * name
Definition: expat.h:151
void decode(boost::any const &, std::string &)
const_iterator end() const
extended_value const & find(std::string const &name) const
ps_atom_t encode(std::string const &)
intermediate_table::table_t operator()(intermediate_table &table, std::string const &name)
extended_value * pre_insert_(std::string const &name, extended_value const &value)
bool putEmptySequence(std::string const &name, bool in_prolog=false)
std::pair< std::string, std::string > complex_t
bool insert(std::string const &name, bool in_prolog, value_tag tag, boost::any const &value)
intermediate_table::sequence_t & operator()(intermediate_table &sequence, std::string const &name)
extended_value::table_t table_t
intermediate_table::table_t & operator()(intermediate_table &table, std::string const &name)
extended_value::atom_t atom_t
extended_value::complex_t complex_t
const_iterator begin() const
void erase(std::string const &name, bool in_prolog=false)
Definition: type_traits.h:56
extended_value::sequence_t sequence_t
const XML_Char int const XML_Char * value
Definition: expat.h:331
bool putNil(std::string const &name, bool in_prolog=false)
std::vector< extended_value > sequence_t
extended_value * locate(std::string const &name)
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
bool exists(std::string const &name) const
bool putEmptyTable(std::string const &name, bool in_prolog=false)
std::enable_if<!b, T > disable_if
Definition: type_traits.h:63
extended_value & update(std::string const &name)
T get(std::string const &name)
std::vector< std::string > split(std::string const &name) const
TRandom3 r(0)
intermediate_table::table_t const & operator()(intermediate_table const &table, std::string const &name)
double T
Definition: Xdiff_gwt.C:5
intermediate_table::sequence_t operator()(intermediate_table &table, std::string const &name)
std::string to_string(ModuleType mt)
Definition: ModuleType.h:32
table_t::const_iterator const_iterator
intermediate_table::sequence_t const & operator()(intermediate_table const &table, std::string const &name)
std::pair< extended_value *, bool > locate_(std::string const &name, bool in_prolog=false)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
enum BeamMode string