LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
coding.h
Go to the documentation of this file.
1 #ifndef fhiclcpp_coding_h
2 #define fhiclcpp_coding_h
3 
4 // ======================================================================
5 //
6 // coding
7 //
8 // ======================================================================
9 //
10 // Notes:
11 //
12 // exception handling
13 //
14 // - For std::pair- and std::tuple- supported decode functions,
15 // exceptions are thrown using std::exception-derived classes since
16 // fhicl::ParameterSet::get_one_ rethrows whatever exception it
17 // receives. If a fhicl::exception is rethrown with a
18 // fhicl::exception, then the cetlib::exception class includes two
19 // prolog/epilog statements instead of one.
20 //
21 // ======================================================================
22 
23 #include "boost/lexical_cast.hpp"
24 #include "boost/numeric/conversion/cast.hpp"
26 #include "fhiclcpp/exception.h"
28 #include "fhiclcpp/fwd.h"
29 #include "fhiclcpp/parse.h"
30 #include "fhiclcpp/type_traits.h"
31 
32 #include <any>
33 #include <array>
34 #include <complex>
35 #include <cstdint>
36 #include <sstream>
37 #include <string>
38 #include <tuple>
39 #include <type_traits>
40 #include <utility>
41 #include <vector>
42 
43 namespace fhicl::detail {
44  using ps_atom_t = std::string;
45  using ps_sequence_t = std::vector<std::any>;
46  using ldbl = long double;
47 
48  inline bool
49  is_sequence(std::any const& val)
50  {
51  return val.type() == typeid(ps_sequence_t);
52  }
53 
54  inline bool
55  is_table(std::any const& val)
56  {
57  return val.type() == typeid(ParameterSetID);
58  }
59 
60  bool is_nil(std::any const& val);
61 
62  // ----------------------------------------------------------------------
63 
64  ps_atom_t encode(std::string const&); // string (w/ quotes)
65  ps_atom_t encode(char const*); // string (w/ quotes)
66  ps_atom_t encode(std::nullptr_t); // nil
67  ps_atom_t encode(bool); // bool
68  ParameterSetID encode(ParameterSet const&); // table
69  ps_atom_t encode(std::uintmax_t); // unsigned
70  template <class T>
72  T const&); // unsigned
73  ps_atom_t encode(std::intmax_t); // signed
74  template <class T>
76  ps_atom_t encode(ldbl); // floating-point
77  template <class T>
78  std::enable_if_t<std::is_floating_point_v<T>, ps_atom_t> encode(
79  T const&); // floating-point
80  template <class T>
81  ps_atom_t encode(std::complex<T> const&); // complex
82  template <class T>
83  ps_sequence_t encode(std::vector<T> const&); // sequence
84  template <class T>
86  T const&); // none of the above
87 
88  // ----------------------------------------------------------------------
89 
90  void decode(std::any const&, std::string&); // string
91  void decode(std::any const&, std::nullptr_t&); // nil
92  void decode(std::any const&, bool&); // bool
93  void decode(std::any const&, ParameterSet&); // table
94  void decode(std::any const&, std::uintmax_t&); // unsigned
95 
96  template <class T>
98  T&); // unsigned
99 
100  void decode(std::any const&, std::intmax_t&); // signed
101 
102  template <class T>
104  T&); // signed
105 
106  void decode(std::any const&, ldbl&); // floating-point
107 
108  template <class T>
109  std::enable_if_t<std::is_floating_point_v<T>> decode(std::any const&,
110  T&); // floating-point
111 
112  void decode(std::any const&, std::complex<ldbl>&); // complex
113 
114  template <class T>
115  void decode(std::any const&, std::complex<T>&); // complex
116 
117  template <class T>
118  void decode(std::any const&, std::vector<T>&); // sequence
119 
120  template <typename U>
121  void decode_tuple(std::any const&, U& tuple); // tuple-type decoding
122 
123  template <typename T, std::size_t SIZE>
124  void
125  decode(std::any const& a, std::array<T, SIZE>& result) // std::array
126  {
127  decode_tuple(a, result);
128  }
129 
130  template <typename KEY, typename VALUE>
131  void
132  decode(std::any const& a, std::pair<KEY, VALUE>& result) // std::pair
133  {
134  decode_tuple(a, result);
135  }
136 
137  template <typename... ARGS>
138  void
139  decode(std::any const& a, std::tuple<ARGS...>& result) // std::tuple
140  {
141  decode_tuple(a, result);
142  }
143 
144  template <unsigned SIZE, typename TUPLE> // tuple support
145  struct per_entry {
146  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
147  };
148 
149  template <typename TUPLE> // tuple support
150  struct per_entry<0, TUPLE> {
151  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
152  };
153 
154  template <class T>
156  T&); // none of the above
157 
158 } // fhicl::detail
159 
160 // ======================================================================
161 
162 template <class T> // unsigned
165 {
166  return encode(uintmax_t(value));
167 }
168 
169 template <class T> // signed
172 {
173  return encode(intmax_t(value));
174 }
175 
176 template <class T> // floating-point
177 std::enable_if_t<std::is_floating_point_v<T>, fhicl::detail::ps_atom_t>
179 {
180  return encode(ldbl(value));
181 }
182 
183 template <class T> // complex
185 fhicl::detail::encode(std::complex<T> const& value)
186 {
187  return '(' + encode(value.real()) + ',' + encode(value.imag()) + ')';
188 }
189 
190 template <class T> // sequence
192 fhicl::detail::encode(std::vector<T> const& value)
193 {
194  ps_sequence_t result;
195  for (auto const& e : value) {
196  result.emplace_back(encode(e));
197  }
198  return result;
199 }
200 
201 template <class T> // none of the above
203 fhicl::detail::encode(T const& value)
204 {
205  return boost::lexical_cast<std::string>(value);
206 }
207 
208 // ----------------------------------------------------------------------
209 
210 //===================================================================
211 // unsigned
212 template <class T>
214 fhicl::detail::decode(std::any const& a, T& result)
215 {
216  std::uintmax_t via;
217  decode(a, via);
218  result = boost::numeric_cast<T>(via);
219 }
220 
221 //====================================================================
222 // signed
223 template <class T>
225 fhicl::detail::decode(std::any const& a, T& result)
226 {
227  std::intmax_t via;
228  decode(a, via);
229  result = boost::numeric_cast<T>(via);
230 }
231 
232 //====================================================================
233 // floating-point
234 template <class T>
235 std::enable_if_t<std::is_floating_point_v<T>>
236 fhicl::detail::decode(std::any const& a, T& result)
237 {
238  ldbl via;
239  decode(a, via);
240  result = via; // boost::numeric_cast<T>(via);
241 }
242 
243 //====================================================================
244 // complex
245 template <class T>
246 void
247 fhicl::detail::decode(std::any const& a, std::complex<T>& result)
248 {
249  std::complex<ldbl> via;
250  decode(a, via);
251  result = {boost::numeric_cast<T>(via.real()),
252  boost::numeric_cast<T>(via.imag())};
253 }
254 
255 //====================================================================
256 // sequence
257 template <class T>
258 void
259 fhicl::detail::decode(std::any const& a, std::vector<T>& result)
260 {
261  if (a.type() == typeid(std::string)) {
262  std::string str;
263  decode(a, str);
264 
265  extended_value xval;
266  std::string unparsed;
267  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(SEQUENCE))
268  throw fhicl::exception(type_mismatch, "error in sequence string:\n")
269  << str << "\nat or before:\n"
270  << unparsed;
271 
272  auto const& seq = fhicl::extended_value::sequence_t(xval);
273  result.clear();
274  T via;
275  for (auto const& e : seq) {
276  decode(e.to_string(), via);
277  result.push_back(via);
278  }
279  }
280 
281  else if (a.type() == typeid(ps_sequence_t)) {
282  ps_sequence_t const& seq = std::any_cast<ps_sequence_t>(a);
283  result.clear();
284  T via;
285  for (auto const& e : seq) {
286  decode(e, via);
287  result.push_back(via);
288  }
289  }
290 
291  else
292  throw fhicl::exception(type_mismatch, "invalid sequence");
293 }
294 
295 //====================================================================
296 // per-entry decode
297 
298 namespace fhicl::detail {
299  template <typename TUPLE, size_t I>
300  auto
302  {
303  std::tuple_element_t<I, TUPLE> result_elem;
304  decode(vec.at(I), result_elem);
305  return result_elem;
306  }
307 
308  template <typename TUPLE, size_t... I>
309  void
311  TUPLE& result,
312  std::index_sequence<I...>)
313  {
314  ((std::get<I>(result) = decode_entry<TUPLE, I>(vec)), ...);
315  }
316 }
317 
318 // tuple-type support
319 template <typename U>
320 void
321 fhicl::detail::decode_tuple(std::any const& a, U& result)
322 {
323  auto const seq = std::any_cast<ps_sequence_t>(a);
324 
325  constexpr std::size_t TUPLE_SIZE = std::tuple_size_v<U>;
326 
327  if (seq.size() != TUPLE_SIZE) {
328  std::ostringstream errmsg;
329  errmsg << "Number of expected arguments (" << TUPLE_SIZE
330  << ") does not match "
331  << "number of FHiCL sequence entries (" << seq.size() << "): [ ";
332  for (auto ca = seq.begin(); ca != seq.cend(); ++ca) {
333  std::string tmp;
334  decode(*ca, tmp);
335  errmsg << tmp;
336  if (ca != seq.cend() - 1) {
337  errmsg << ", ";
338  }
339  }
340  errmsg << " ]";
341  throw std::length_error(errmsg.str());
342  }
343 
344  decode_tuple_entries(seq, result, std::make_index_sequence<TUPLE_SIZE>());
345  // per_entry<TUPLE_SIZE - 1, U>::decode_tuple_entry(seq, result);
346 }
347 
348 //====================================================================
349 template <class T> // none of the above
351 fhicl::detail::decode(std::any const& a, T& result)
352 {
353  result = std::any_cast<T>(a);
354 }
355 
356 // ======================================================================
357 
358 #endif /* fhiclcpp_coding_h */
359 
360 // Local Variables:
361 // mode: c++
362 // End:
bool parse_value_string(std::string const &s, extended_value &v, std::string &unparsed)
Definition: parse.cc:658
bool is_a(value_tag const t) const noexcept
ps_atom_t encode(std::string const &)
Definition: coding.cc:83
long double ldbl
Definition: coding.h:46
Float_t tmp
Definition: plot.C:35
void decode_tuple(std::any const &, U &tuple)
Definition: coding.h:321
void decode(std::any const &, std::string &)
auto decode_entry(ps_sequence_t const &vec)
Definition: coding.h:301
void decode_tuple_entries(ps_sequence_t const &vec, TUPLE &result, std::index_sequence< I... >)
Definition: coding.h:310
Definition: coding.h:145
std::vector< std::any > ps_sequence_t
Definition: coding.h:45
static void decode_tuple_entry(ps_sequence_t const &, TUPLE &)
std::vector< extended_value > sequence_t
bool is_nil(std::any const &val)
Definition: coding.cc:71
double value
Definition: spectrum.C:18
std::string ps_atom_t
Definition: coding.h:44
typename disable_if< b, T >::type disable_if_t
Definition: type_traits.h:69
bool is_table(std::any const &val)
Definition: coding.h:55
Float_t e
Definition: plot.C:35
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool is_sequence(std::any const &val)
Definition: coding.h:49