LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ParameterSet.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_ParameterSet_h
2 #define fhiclcpp_ParameterSet_h
3 
4 // ======================================================================
5 //
6 // ParameterSet
7 //
8 // ======================================================================
9 
10 #include "cetlib_except/demangle.h"
12 #include "fhiclcpp/coding.h"
17 #include "fhiclcpp/exception.h"
18 #include "fhiclcpp/fwd.h"
19 
20 #include <any>
21 #include <functional>
22 #include <map>
23 #include <optional>
24 #include <sstream>
25 #include <string>
26 #include <typeinfo>
27 #include <unordered_map>
28 #include <vector>
29 
30 // ----------------------------------------------------------------------
31 
32 namespace cetlib {
33  class filepath_maker;
34 }
35 
37 public:
40  using annot_t = std::unordered_map<std::string, std::string>;
41 
42  // compiler generates default c'tor, d'tor, copy c'tor, copy assignment
43 
44  static ParameterSet make(intermediate_table const& tbl);
45  static ParameterSet make(extended_value const& xval);
46  static ParameterSet make(std::string const& str);
47  static ParameterSet make(std::string const& filename,
48  cet::filepath_maker& maker);
49 
50  // observers:
51  bool is_empty() const;
52  ParameterSetID id() const;
53 
54  std::string to_string() const;
55  std::string to_compact_string() const;
56 
57  std::string to_indented_string() const;
58  std::string to_indented_string(unsigned initial_indent_level) const;
59  std::string to_indented_string(unsigned initial_indent_level,
60  bool annotate) const;
61  std::string to_indented_string(unsigned initial_indent_level,
62  detail::print_mode pm) const;
63 
64  std::vector<std::string> get_names() const;
65  std::vector<std::string> get_pset_names() const;
66  std::vector<std::string> get_all_keys() const;
67 
68  // retrievers (nested key OK):
69  bool has_key(std::string const& key) const;
70  bool is_key_to_table(std::string const& key) const;
71  bool is_key_to_sequence(std::string const& key) const;
72  bool is_key_to_atom(std::string const& key) const;
73 
74  template <class T>
75  std::optional<T> get_if_present(std::string const& key) const;
76  template <class T, class Via>
77  std::optional<T> get_if_present(std::string const& key,
78  T convert(Via const&)) const;
79 
80  // Obsolete interface
81  template <class T>
82  bool get_if_present(std::string const& key, T& value) const;
83  template <class T, class Via>
84  bool get_if_present(std::string const& key,
85  T& value,
86  T convert(Via const&)) const;
87 
88  template <class T>
89  T get(std::string const& key) const;
90  template <class T, class Via>
91  T get(std::string const& key, T convert(Via const&)) const;
92  template <class T>
93  T get(std::string const& key, T const& default_value) const;
94  template <class T, class Via>
95  T get(std::string const& key,
96  T const& default_value,
97  T convert(Via const&)) const;
98 
99  std::string get_src_info(std::string const& key) const;
100 
101  // Facility to traverse the ParameterSet tree
102  void walk(ParameterSetWalker& psw) const;
103 
104  // inserters (key must be local: no nesting):
105  void put(std::string const& key); // Implicit nil value.
106  template <class T> // Fail on preexisting key.
107  void put(std::string const& key, T const& value);
108  void put_or_replace(std::string const& key); // Implicit nil value.
109  template <class T> // Succeed.
110  void put_or_replace(std::string const& key, T const& value);
111  template <class T> // Fail if preexisting key of incompatible type.
112  void put_or_replace_compatible(std::string const& key, T const& value);
113 
114  // deleters:
115  bool erase(std::string const& key);
116 
117  // comparators:
118  bool operator==(ParameterSet const& other) const;
119  bool operator!=(ParameterSet const& other) const;
120 
121 private:
122  using map_t = std::map<std::string, std::any>;
124 
128 
129  // Private inserters.
130  void insert_(std::string const& key, std::any const& value);
131  void insert_or_replace_(std::string const& key, std::any const& value);
132  void insert_or_replace_compatible_(std::string const& key,
133  std::any const& value);
134 
135  std::string to_string_(bool compact = false) const;
136  std::string stringify_(std::any const& a, bool compact = false) const;
137 
138  bool key_is_type_(std::string const& key,
139  std::function<bool(std::any const&)> func) const;
140 
141  // Local retrieval only.
142  template <class T>
143  std::optional<T> get_one_(std::string const& key) const;
144  bool find_one_(std::string const& key) const;
145  std::optional<ParameterSet> descend_(
146  std::vector<std::string> const& names) const;
147 
148 }; // ParameterSet
149 
150 // ======================================================================
151 // Explicit instantiations for commonly used types
152 
153 #define _DECODE_ATOM_(T) void fhicl::detail::decode<T>(std::any const&, T&)
154 
155 #define _DECODE_SEQUENCE_(T) \
156  void fhicl::detail::decode<T::value_type>(std::any const&, T&)
157 
158 #define _GET_ONE_(T) \
159  std::optional<T> fhicl::ParameterSet::get_one_<T>(std::string const&) const
160 
161 #define _GET(T) T fhicl::ParameterSet::get<T>(std::string const&) const
162 
163 #define _GET_WITH_DEFAULT(T) \
164  T fhicl::ParameterSet::get<T>(std::string const&, T const&) const
165 
166 #define _GET_IF_PRESENT(T) \
167  std::optional<T> fhicl::ParameterSet::get_if_present<T>(std::string const&) \
168  const
169 
170 #define _EXTERN_INSTANTIATE_GET(FHICL_TYPE, T) \
171  extern template _DECODE_##FHICL_TYPE##_(T); \
172  extern template _GET_ONE_(T); \
173  extern template _GET(T); \
174  extern template _GET_WITH_DEFAULT(T); \
175  extern template _GET_IF_PRESENT(T)
176 
177 _EXTERN_INSTANTIATE_GET(ATOM, bool);
178 _EXTERN_INSTANTIATE_GET(ATOM, int);
179 _EXTERN_INSTANTIATE_GET(ATOM, unsigned);
180 _EXTERN_INSTANTIATE_GET(ATOM, float);
181 _EXTERN_INSTANTIATE_GET(ATOM, double);
182 _EXTERN_INSTANTIATE_GET(ATOM, std::string);
184 
185 // Instantiate std::vector of same types except 'bool'.
186 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<int>);
187 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<unsigned>);
188 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<float>);
189 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<double>);
190 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<std::string>);
191 _EXTERN_INSTANTIATE_GET(SEQUENCE, std::vector<fhicl::ParameterSet>);
192 
193 // ======================================================================
194 
195 inline std::string
197 {
198  return to_string_();
199 }
200 
201 inline std::string
203 {
204  return to_string_(true);
205 }
206 
207 inline bool
208 fhicl::ParameterSet::is_key_to_table(std::string const& key) const
209 {
210  return key_is_type_(key, &detail::is_table);
211 }
212 
213 inline bool
214 fhicl::ParameterSet::is_key_to_sequence(std::string const& key) const
215 {
216  return key_is_type_(key, &detail::is_sequence);
217 }
218 
219 inline bool
220 fhicl::ParameterSet::is_key_to_atom(std::string const& key) const
221 {
222  return key_is_type_(key, [](std::any const& a) {
223  return !(detail::is_sequence(a) || detail::is_table(a));
224  });
225 }
226 
227 template <class T>
228 void
229 fhicl::ParameterSet::put(std::string const& key, T const& value)
230 {
231  auto insert = [this, &value](auto const& key) {
232  using detail::encode;
233  this->insert_(key, std::any(encode(value)));
234  };
235  detail::try_insert(insert, key);
236 }
237 
238 template <class T>
239 void
240 fhicl::ParameterSet::put_or_replace(std::string const& key, T const& value)
241 {
242  auto insert_or_replace = [this, &value](auto const& key) {
243  using detail::encode;
244  this->insert_or_replace_(key, std::any(encode(value)));
245  srcMapping_.erase(key);
246  };
247  detail::try_insert(insert_or_replace, key);
248 }
249 
250 template <class T>
251 void
253  T const& value)
254 {
255  auto insert_or_replace_compatible = [this, &value](auto const& key) {
256  using detail::encode;
257  this->insert_or_replace_compatible_(key, std::any(encode(value)));
258  srcMapping_.erase(key);
259  };
260  detail::try_insert(insert_or_replace_compatible, key);
261 }
262 
263 // ----------------------------------------------------------------------
264 
265 template <class T>
266 std::optional<T>
267 fhicl::ParameterSet::get_if_present(std::string const& key) const
268 {
269  auto keys = detail::get_names(key);
270  if (auto ps = descend_(keys.tables())) {
271  return ps->get_one_<T>(keys.last());
272  }
273  return std::nullopt;
274 }
275 
276 template <class T, class Via>
277 std::optional<T>
278 fhicl::ParameterSet::get_if_present(std::string const& key,
279  T convert(Via const&)) const
280 {
281  auto go_between = get_if_present<Via>(key);
282  if (not go_between) {
283  return std::nullopt;
284  }
285  return std::make_optional(convert(*go_between));
286 } // get_if_present<>()
287 
288 template <class T>
289 bool
290 fhicl::ParameterSet::get_if_present(std::string const& key, T& value) const
291 {
292  if (auto present_parameter = get_if_present<T>(key)) {
293  value = *present_parameter;
294  return true;
295  }
296  return false;
297 }
298 
299 template <class T, class Via>
300 bool
301 fhicl::ParameterSet::get_if_present(std::string const& key,
302  T& result,
303  T convert(Via const&)) const
304 {
305  if (auto present_parameter = get_if_present<T>(key, convert)) {
306  result = *present_parameter;
307  return true;
308  }
309  return false;
310 } // get_if_present<>()
311 
312 template <class T>
313 T
314 fhicl::ParameterSet::get(std::string const& key) const
315 {
316  auto result = get_if_present<T>(key);
317  return result ? *result : throw fhicl::exception(cant_find, key);
318 }
319 
320 template <class T, class Via>
321 T
322 fhicl::ParameterSet::get(std::string const& key, T convert(Via const&)) const
323 {
324  auto result = get_if_present<T>(key, convert);
325  return result ? *result : throw fhicl::exception(cant_find, key);
326 }
327 
328 template <class T>
329 T
330 fhicl::ParameterSet::get(std::string const& key, T const& default_value) const
331 {
332  auto result = get_if_present<T>(key);
333  return result ? *result : default_value;
334 }
335 
336 template <class T, class Via>
337 T
338 fhicl::ParameterSet::get(std::string const& key,
339  T const& default_value,
340  T convert(Via const&)) const
341 {
342  auto result = get_if_present<T>(key, convert);
343  return result ? *result : default_value;
344 }
345 
346 // ----------------------------------------------------------------------
347 
348 inline bool
350 {
351  return id() == other.id();
352 }
353 
354 inline bool
356 {
357  return !operator==(other);
358 }
359 
360 // ----------------------------------------------------------------------
361 
362 template <class T>
363 std::optional<T>
364 fhicl::ParameterSet::get_one_(std::string const& key) const
365 {
366  T value;
367  try {
368  auto skey = detail::get_sequence_indices(key);
369 
370  map_iter_t it = mapping_.find(skey.name());
371  if (it == mapping_.end()) {
372  return std::nullopt;
373  }
374 
375  auto a = it->second;
376  if (!detail::find_an_any(
377  skey.indices().cbegin(), skey.indices().cend(), a)) {
379  }
380 
381  using detail::decode;
382  decode(a, value);
383  return std::make_optional(value);
384  }
385  catch (fhicl::exception const& e) {
386  std::ostringstream errmsg;
387  errmsg << "\nUnsuccessful attempt to convert FHiCL parameter '" << key
388  << "' to type '" << cet::demangle_symbol(typeid(value).name())
389  << "'.\n\n"
390  << "[Specific error:]";
391  throw fhicl::exception(type_mismatch, errmsg.str(), e);
392  }
393  catch (std::exception const& e) {
394  std::ostringstream errmsg;
395  errmsg << "\nUnsuccessful attempt to convert FHiCL parameter '" << key
396  << "' to type '" << cet::demangle_symbol(typeid(value).name())
397  << "'.\n\n"
398  << "[Specific error:]\n"
399  << e.what() << "\n\n";
400  throw fhicl::exception(type_mismatch, errmsg.str());
401  }
402 }
403 
404 // ----------------------------------------------------------------------
405 
406 namespace fhicl {
407  template <>
408  void ParameterSet::put(std::string const& key,
409  fhicl::extended_value const& value);
410 }
411 
412 // ======================================================================
413 
414 #endif /* fhiclcpp_ParameterSet_h */
415 
416 // Local Variables:
417 // mode: c++
418 // End:
bool operator!=(ParameterSet const &other) const
Definition: ParameterSet.h:355
std::unique_ptr< InputSource > make(fhicl::ParameterSet const &conf, InputSourceDescription &desc)
Keys get_names(std::string const &key)
std::unordered_map< std::string, std::string > annot_t
Definition: ParameterSet.h:40
intermediate_table::const_iterator const_iterator
#define _EXTERN_INSTANTIATE_GET(FHICL_TYPE, T)
Definition: ParameterSet.h:170
map_t::const_iterator map_iter_t
Definition: ParameterSet.h:123
::fhicl::detail::ps_atom_t encode(Interval< Args... > const &iv)
Encodes a quantity interval into a FHiCL parameter set atom.
std::vector< std::any > ps_sequence_t
Definition: coding.h:45
bool is_key_to_sequence(std::string const &key) const
Definition: ParameterSet.h:214
void try_insert(L l, std::string const &key)
Definition: try_blocks.h:11
bool is_key_to_table(std::string const &key) const
Definition: ParameterSet.h:208
std::map< std::string, std::any > map_t
Definition: ParameterSet.h:122
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
parameter set interface
T get(std::string const &key) const
Definition: ParameterSet.h:314
bool operator==(ParameterSet const &other) const
Definition: ParameterSet.h:349
void put_or_replace_compatible(std::string const &key, T const &value)
Definition: ParameterSet.h:252
fhicl::detail::ps_atom_t ps_atom_t
Definition: ParameterSet.h:38
std::string to_compact_string() const
Definition: ParameterSet.h:202
bool find_an_any(std::vector< std::size_t >::const_iterator it, std::vector< std::size_t >::const_iterator const cend, std::any &a)
SequenceKey get_sequence_indices(std::string const &key)
fhicl::detail::ps_sequence_t ps_sequence_t
Definition: ParameterSet.h:39
double value
Definition: spectrum.C:18
ParameterSetID id() const
void decode(std::any const &src, Interval< Args... > &iv)
Decodes an interval.
std::string ps_atom_t
Definition: coding.h:44
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:267
std::optional< T > get_one_(std::string const &key) const
Definition: ParameterSet.h:364
bool is_key_to_atom(std::string const &key) const
Definition: ParameterSet.h:220
bool operator!=(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Never admit a infinite_endcount_iterator to be equal to anything else.
Definition: counter.h:266
bool is_table(std::any const &val)
Definition: coding.h:55
ParameterSetID id_
Definition: ParameterSet.h:127
Float_t e
Definition: plot.C:35
void put_or_replace(std::string const &key)
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Definition: counter.h:278
void put(std::string const &key)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool is_sequence(std::any const &val)
Definition: coding.h:49
std::string to_string() const
Definition: ParameterSet.h:196