LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 std::any.
25 //
26 // 2. The std::any in a ParameterSet may not be the same type as the
27 // std::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<std::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 std::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 std::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 "fhiclcpp/coding.h"
52 #include "fhiclcpp/exception.h"
54 #include "fhiclcpp/fwd.h"
55 #include "fhiclcpp/type_traits.h"
56 
57 #include <any>
58 #include <complex>
59 #include <string>
60 #include <type_traits>
61 #include <vector>
62 
63 // ----------------------------------------------------------------------
64 
66 public:
68  // Simple interface:
69  bool empty() const;
70 
71  bool exists(std::string const& key) const;
72 
73  void erase(std::string const& key, bool in_prolog = false);
74 
75  template <typename T>
76  T get(std::string const& name);
77 
78  bool put(std::string const& name,
79  std::string const& value, // String.
80  bool in_prolog = false);
81  bool put(std::string const& name,
82  char const* value, // String.
83  bool in_prolog = false);
84  bool put(std::string const& name,
85  bool value, // Boolean.
86  bool in_prolog = false);
87  template <typename T>
88  bool put(std::string const& name,
89  std::complex<T> const& value, // Complex.
90  bool in_prolog = false);
91  template <typename T>
92  bool put(std::string const& name,
93  std::vector<T> const& value, // Sequence.
94  bool in_prolog = false);
95  template <typename T>
96  std::enable_if_t<tt::is_numeric<T>::value, bool> put(std::string const& name,
97  T value, // Number
98  bool in_prolog = false);
99 
100  bool putEmptySequence(std::string const& name,
101  bool in_prolog = false); // Empty Sequence.
102  bool putEmptyTable(std::string const& name,
103  bool in_prolog = false); // Empty Table.
104  bool putNil(std::string const& name,
105  bool in_prolog = false); // Nil.
106 
108  // Expert interface.
109  // Typedefs.
116 
117  const_iterator begin() const;
118  const_iterator end() const;
119 
120  // Flexible insert interface.
121  bool insert(std::string const& key,
122  bool in_prolog,
123  value_tag tag,
124  std::any const& value);
125  bool insert(std::string const& key, extended_value const& value);
126  bool insert(std::string const& key, extended_value&& value);
127 
129  extended_value const& find(std::string const& key) const;
130 
132  extended_value* locate(std::string const& key);
133 
135  extended_value& update(std::string const& key);
136 
137 private:
138  // Do all the work required to find somewhere to put the new
139  // value. Called by insert().
140  extended_value* pre_insert_(std::string const& key,
141  extended_value const& value);
142 
143  // Return an item with a bool indicating whether it may be updated.
144  std::pair<extended_value*, bool> locate_(std::string const& key,
145  bool in_prolog = false);
146 
147  static std::vector<std::string> split(std::string const& key);
148 
150 
151 }; // intermediate_table
152 
153 namespace fhicl::detail {
154 
155  // Template declaration (no general definition).
156  template <typename T, typename Enable = void>
158 
159  // Partial specialization for value types.
160  template <typename T>
161  class it_value_get<T,
162  typename tt::disable_if<std::is_reference_v<T> ||
163  std::is_pointer_v<T>>::type> {
164  public:
165  T
166  operator()(intermediate_table& table, std::string const& key)
167  {
168  T result;
169  detail::decode(table.find(key).value, result);
170  return result;
171  }
172  };
173 
174  // Partial specialization for std::complex<U>.
175  template <typename U>
177  std::complex<U>,
178  typename tt::disable_if<std::is_reference_v<std::complex<U>> ||
179  std::is_pointer_v<std::complex<U>>>::type> {
180  public:
181  std::complex<U>
182  operator()(intermediate_table& table, std::string const& key)
183  {
184  intermediate_table::complex_t c(table.find(key));
185  U r, i;
186  detail::decode(c.first, r);
187  detail::decode(c.second, i);
188  return std::complex<U>(r, i);
189  }
190  };
191 
192  // Full specialization for sequence_t
193  template <>
195  public:
197  operator()(intermediate_table& table, std::string const& key)
198  {
199  return std::any_cast<intermediate_table::sequence_t>(
200  table.find(key).value);
201  }
202  };
203 
204  // Full specialization for sequence_t&: will throw if not writable
205  template <>
207  public:
208  intermediate_table::sequence_t&
209  operator()(intermediate_table& table, std::string const& key)
210  {
211  auto item = table.locate(key);
212  if (item != nullptr) {
213  return std::any_cast<intermediate_table::sequence_t&>(item->value);
214  }
216  << "Requested non-updatable parameter \"" << key << "\" for update.\n";
217  }
218  };
219 
220  // Full specialization for sequence_t const&
221  template <>
223  public:
224  intermediate_table::sequence_t const&
225  operator()(intermediate_table& table, std::string const& key)
226  {
227  return std::any_cast<intermediate_table::sequence_t const&>(
228  table.find(key).value);
229  }
230  };
231 
232  // Full specialization for table_t
233  template <>
235  public:
237  operator()(intermediate_table& table, std::string const& key)
238  {
239  return std::any_cast<intermediate_table::table_t>(table.find(key).value);
240  }
241  };
242 
243  // Full specialization for table_t&: will throw if not writable
244  template <>
246  public:
247  intermediate_table::table_t&
248  operator()(intermediate_table& table, std::string const& key)
249  {
250  auto item = table.locate(key);
251  if (item != nullptr) {
252  return std::any_cast<intermediate_table::table_t&>(item->value);
253  }
255  << "Requested non-updatable parameter " << key << " for update.\n";
256  }
257  };
258 
259  // Full specialization for table_t const&
260  template <>
262  public:
263  intermediate_table::table_t const&
264  operator()(intermediate_table& table, std::string const& key)
265  {
266  return std::any_cast<intermediate_table::table_t const&>(
267  table.find(key).value);
268  }
269  };
270 }
271 
272 template <typename T>
273 inline T
274 fhicl::intermediate_table::get(std::string const& key)
275 {
276  static detail::it_value_get<T> getter;
277  return getter(*this, key);
278 }
279 
280 inline bool
281 fhicl::intermediate_table::put(std::string const& key,
282  std::string const& value, // String.
283  bool in_prolog)
284 {
285  return insert(key, in_prolog, STRING, detail::encode(value));
286 }
287 
288 inline bool
289 fhicl::intermediate_table::put(std::string const& key,
290  char const* value, // String.
291  bool const in_prolog)
292 {
293  return insert(key, in_prolog, STRING, detail::encode(value));
294 }
295 
296 inline bool
297 fhicl::intermediate_table::put(std::string const& key,
298  bool const value, // Boolean.
299  bool const in_prolog)
300 {
301  return insert(key, in_prolog, BOOL, detail::encode(value));
302 }
303 
304 template <typename T>
305 bool
306 fhicl::intermediate_table::put(std::string const& key,
307  std::complex<T> const& value, // Complex.
308  bool const in_prolog)
309 {
310  return insert(
311  key,
312  in_prolog,
313  COMPLEX,
314  complex_t(detail::encode(value.real()), detail::encode(value.imag())));
315 }
316 
317 template <typename T>
318 inline bool
319 fhicl::intermediate_table::put(std::string const& key,
320  std::vector<T> const& value, // Sequence.
321  bool const in_prolog)
322 {
323  bool result = putEmptySequence(key, in_prolog);
324  if (!result) {
325  return result;
326  }
327  size_t count(0);
328  for (auto const& item : value) {
329  result =
330  result && put(key + "[" + std::to_string(count++) + "]", item, in_prolog);
331  }
332  return result;
333 }
334 
335 template <typename T>
337 fhicl::intermediate_table::put(std::string const& key,
338  T const value, // Number
339  bool const in_prolog)
340 {
341  return insert(key, in_prolog, NUMBER, detail::encode(value));
342 }
343 
344 inline bool
346  bool const in_prolog) // Sequence.
347 {
348  return insert(key, in_prolog, SEQUENCE, sequence_t{});
349 }
350 
351 inline bool
353  bool const in_prolog) // Table.
354 {
355  return insert(key, in_prolog, TABLE, table_t{});
356 }
357 
358 inline bool
359 fhicl::intermediate_table::putNil(std::string const& key,
360  bool const in_prolog) // Nil.
361 {
362  return insert(key, in_prolog, NIL, detail::encode(nullptr));
363 }
364 
365 inline fhicl::extended_value*
366 fhicl::intermediate_table::locate(std::string const& key)
367 {
368  extended_value* result = nullptr;
369  auto located = locate_(key);
370  if (located.second) {
371  result = located.first;
372  }
373  return result;
374 }
375 
376 inline fhicl::extended_value&
377 fhicl::intermediate_table::update(std::string const& key)
378 {
379  auto located = locate_(key);
380  if (!located.second) {
382  << "Requested non-modifiable item \"" << key << "\" for update.\n";
383  }
384  return *located.first;
385 }
386 
387 #endif /* fhiclcpp_intermediate_table_h */
388 
389 // Local Variables:
390 // mode: c++
391 // End:
TRandom r
Definition: spectrum.C:23
iter< iterator_tag, std::pair< Key const, T >> iterator
Definition: stdmap_shims.h:139
extended_value * locate(std::string const &key)
const_iterator end() const
ps_atom_t encode(std::string const &)
Definition: coding.cc:83
intermediate_table::sequence_t & operator()(intermediate_table &table, std::string const &key)
bool insert(std::string const &key, bool in_prolog, value_tag tag, std::any const &value)
bool putEmptySequence(std::string const &name, bool in_prolog=false)
STL namespace.
intermediate_table::sequence_t const & operator()(intermediate_table &table, std::string const &key)
std::pair< std::string, std::string > complex_t
void decode(std::any const &, std::string &)
Definition: type_traits.h:61
extended_value::complex_t complex_t
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
const_iterator begin() const
intermediate_table::table_t operator()(intermediate_table &table, std::string const &key)
intermediate_table::table_t const & operator()(intermediate_table &table, std::string const &key)
bool putNil(std::string const &name, bool in_prolog=false)
intermediate_table::sequence_t operator()(intermediate_table &table, std::string const &key)
extended_value::sequence_t sequence_t
std::vector< extended_value > sequence_t
shims::map< std::string, extended_value > table_t
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
double value
Definition: spectrum.C:18
bool exists(std::string const &key) const
fhicl::extended_value::sequence_t sequence_t
bool putEmptyTable(std::string const &name, bool in_prolog=false)
std::enable_if<!b, T > disable_if
Definition: type_traits.h:66
extended_value * pre_insert_(std::string const &key, extended_value const &value)
void erase(std::string const &key, bool in_prolog=false)
extended_value const & find(std::string const &key) const
extended_value & update(std::string const &key)
static std::vector< std::string > split(std::string const &key)
T get(std::string const &name)
std::pair< extended_value *, bool > locate_(std::string const &key, bool in_prolog=false)
extended_value::atom_t atom_t
intermediate_table::table_t & operator()(intermediate_table &table, std::string const &key)
iter< iterator_tag, std::pair< Key const, T > const > const_iterator
Definition: stdmap_shims.h:140
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33