LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
intermediate_table.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_intermediate_table_h
2 #define fhiclcpp_intermediate_table_h
3 
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.
19 
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 //
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 
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>
98  typename std::enable_if<tt::is_numeric<T>::value, bool>::type put(
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 
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 
132  extended_value const& find(std::string const& name) const;
133 
135  extended_value* locate(std::string const& name);
136 
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().
143  extended_value* pre_insert_(std::string const& name,
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, bool in_prolog = false);
148 
149  std::vector<std::string> split(std::string const& name) const;
150 
152 
153 }; // intermediate_table
154 
155 namespace fhicl {
156  namespace detail {
157 
158  // Template declaration (no general definition).
159  template <typename T, typename Enable = void>
161 
162  // Partial specialization for value types.
163  template <typename T>
165  T,
166  typename tt::disable_if<std::is_reference<T>::value ||
167  std::is_pointer<T>::value>::type> {
168  public:
169  T
170  operator()(intermediate_table& table, std::string const& name)
171  {
172  T result;
173  detail::decode(table.find(name).value, result);
174  return result;
175  }
176  };
177 
178  // Partial specialization for std::complex<U>.
179  template <typename U>
181  std::complex<U>,
182  typename tt::disable_if<std::is_reference<std::complex<U>>::value ||
183  std::is_pointer<std::complex<U>>::value>::type> {
184  public:
185  std::complex<U>
186  operator()(intermediate_table& table, std::string const& name)
187  {
188  intermediate_table::complex_t c(table.find(name));
189  U r, i;
190  detail::decode(c.first, r);
191  detail::decode(c.second, i);
192  return std::complex<U>(r, i);
193  }
194  };
195 
196  // Full specialization for sequence_t
197  template <>
199  public:
201  operator()(intermediate_table& table, std::string const& name)
202  {
203  return boost::any_cast<intermediate_table::sequence_t>(
204  table.find(name).value);
205  }
206  };
207 
208  // Full specialization for sequence_t &: will throw if not writable
209  template <>
211  public:
212  intermediate_table::sequence_t&
213  operator()(intermediate_table& sequence, std::string const& name)
214  {
215  auto item = sequence.locate(name);
216  if (item != nullptr) {
217  return boost::any_cast<intermediate_table::sequence_t&>(item->value);
218  } else {
220  << "Requested non-updatable parameter \"" << name
221  << "\" for update.\n";
222  }
223  }
224  };
225 
226  // Full specialization for sequence_t const &
227  template <>
229  public:
230  intermediate_table::sequence_t const&
231  operator()(intermediate_table const& table, std::string const& name)
232  {
233  return boost::any_cast<intermediate_table::sequence_t const&>(
234  table.find(name).value);
235  }
236  };
237 
238  // Full specialization for table_t
239  template <>
241  public:
243  operator()(intermediate_table& table, std::string const& name)
244  {
245  return boost::any_cast<intermediate_table::table_t>(
246  table.find(name).value);
247  }
248  };
249 
250  // Full specialization for table_t &: will throw if not writable
251  template <>
253  public:
254  intermediate_table::table_t&
255  operator()(intermediate_table& table, std::string const& name)
256  {
257  auto item = table.locate(name);
258  if (item != nullptr) {
259  return boost::any_cast<intermediate_table::table_t&>(item->value);
260  } else {
262  << "Requested non-updatable parameter " << name << " for update.\n";
263  }
264  }
265  };
266 
267  // Full specialization for table_t const &
268  template <>
270  public:
271  intermediate_table::table_t const&
272  operator()(intermediate_table const& table, std::string const& name)
273  {
274  return boost::any_cast<intermediate_table::table_t const&>(
275  table.find(name).value);
276  }
277  };
278  }
279 }
280 
281 template <typename T>
282 inline T
283 fhicl::intermediate_table::get(std::string const& name)
284 {
285  static detail::it_value_get<T> getter;
286  return getter(*this, name);
287 }
288 
289 inline bool
290 fhicl::intermediate_table::put(std::string const& name,
291  std::string const& value, // String.
292  bool in_prolog)
293 {
294  return insert(name, in_prolog, STRING, detail::encode(value));
295 }
296 
297 inline bool
298 fhicl::intermediate_table::put(std::string const& name,
299  char const* value, // String.
300  bool in_prolog)
301 {
302  return insert(name, in_prolog, STRING, detail::encode(value));
303 }
304 
305 inline bool
306 fhicl::intermediate_table::put(std::string const& name,
307  bool value, // Boolean.
308  bool in_prolog)
309 {
310  return insert(name, in_prolog, BOOL, detail::encode(value));
311 }
312 
313 template <typename T>
314 bool
315 fhicl::intermediate_table::put(std::string const& name,
316  std::complex<T> const& value, // Complex.
317  bool in_prolog)
318 {
319  return insert(
320  name,
321  in_prolog,
322  COMPLEX,
323  complex_t(detail::encode(value.real()), detail::encode(value.imag())));
324 }
325 
326 template <typename T>
327 inline bool
328 fhicl::intermediate_table::put(std::string const& name,
329  std::vector<T> const& value, // Sequence.
330  bool in_prolog)
331 {
332  bool result = putEmptySequence(name, in_prolog);
333  if (!result) {
334  return result;
335  }
336  size_t count(0);
337  for (auto const& item : value) {
338  result = result &&
339  put(name + "[" + std::to_string(count++) + "]", item, in_prolog);
340  }
341  return result;
342 }
343 
344 template <typename T>
345 inline typename std::enable_if<tt::is_numeric<T>::value, bool>::type
346 fhicl::intermediate_table::put(std::string const& name,
347  T value, // Number
348  bool in_prolog)
349 {
350  return insert(name, in_prolog, NUMBER, detail::encode(value));
351 }
352 
354  std::string const& name,
355  bool in_prolog) // Sequence.
356 {
357  return insert(name, in_prolog, SEQUENCE, sequence_t());
358 }
359 
360 inline bool fhicl::intermediate_table::putEmptyTable(std::string const& name,
361  bool in_prolog) // Table.
362 {
363  return insert(name, in_prolog, TABLE, table_t());
364 }
365 
366 inline bool fhicl::intermediate_table::putNil(std::string const& name,
367  bool in_prolog) // Nil.
368 {
369  return insert(name, in_prolog, NIL, detail::encode((void*)0));
370 }
371 
372 inline fhicl::extended_value*
373 fhicl::intermediate_table::locate(std::string const& name)
374 {
375  extended_value* result = nullptr;
376  auto located = locate_(name);
377  if (located.second) {
378  result = located.first;
379  }
380  return result;
381 }
382 
383 inline fhicl::extended_value&
384 fhicl::intermediate_table::update(std::string const& name)
385 {
386  auto located = locate_(name);
387  if (!located.second) {
389  << "Requested non-modifiable item \"" << name << "\" for update.\n";
390  }
391  return *located.first;
392 }
393 
394 #endif /* fhiclcpp_intermediate_table_h */
395 
396 // Local Variables:
397 // mode: c++
398 // End:
void decode(boost::any const &, std::string &)
std::pair< extended_value *, bool > locate_(std::string const &name, bool in_prolog=false)
const_iterator end() const
ps_atom_t encode(std::string const &)
Definition: coding.cc:87
intermediate_table::table_t operator()(intermediate_table &table, std::string const &name)
bool putEmptySequence(std::string const &name, bool in_prolog=false)
STL namespace.
std::pair< std::string, std::string > complex_t
intermediate_table::sequence_t & operator()(intermediate_table &sequence, std::string const &name)
void erase(std::string const &name, bool in_prolog=false)
extended_value::table_t table_t
extended_value * pre_insert_(std::string const &name, extended_value const &value)
intermediate_table::table_t & operator()(intermediate_table &table, std::string const &name)
extended_value::atom_t atom_t
extended_value::complex_t complex_t
Definition: type_traits.h:56
extended_value::sequence_t sequence_t
const_iterator begin() const
parameter set interface
bool putNil(std::string const &name, bool in_prolog=false)
std::vector< extended_value > sequence_t
extended_value * locate(std::string const &name)
extended_value const & find(std::string const &name) const
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
fhicl::extended_value::sequence_t sequence_t
bool putEmptyTable(std::string const &name, bool in_prolog=false)
bool insert(std::string const &name, bool in_prolog, value_tag tag, boost::any const &value)
std::enable_if<!b, T > disable_if
Definition: type_traits.h:63
std::string value(boost::any const &)
extended_value & update(std::string const &name)
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
T get(std::string const &name)
intermediate_table::table_t const & operator()(intermediate_table const &table, std::string const &name)
intermediate_table::sequence_t operator()(intermediate_table &table, std::string const &name)
bool exists(std::string const &name) const
table_t::const_iterator const_iterator
intermediate_table::sequence_t const & operator()(intermediate_table const &table, std::string const &name)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::vector< std::string > split(std::string const &name) const