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 {
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 decode(std::any const& a, std::array<T, SIZE>& result) // std::array
125  {
126  decode_tuple(a, result);
127  }
128 
129  template <typename KEY, typename VALUE>
130  void decode(std::any const& a, std::pair<KEY, VALUE>& result) // std::pair
131  {
132  decode_tuple(a, result);
133  }
134 
135  template <typename... ARGS>
136  void decode(std::any const& a, std::tuple<ARGS...>& result) // std::tuple
137  {
138  decode_tuple(a, result);
139  }
140 
141  template <unsigned SIZE, typename TUPLE> // tuple support
142  struct per_entry {
143  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
144  };
145 
146  template <typename TUPLE> // tuple support
147  struct per_entry<0, TUPLE> {
148  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
149  };
150 
151  template <class T>
153  T&); // none of the above
154 
155 } // fhicl::detail
156 
157 // ======================================================================
158 
159 template <class T> // unsigned
162 {
163  return encode(uintmax_t(value));
164 }
165 
166 template <class T> // signed
169 {
170  return encode(intmax_t(value));
171 }
172 
173 template <class T> // floating-point
174 std::enable_if_t<std::is_floating_point_v<T>, fhicl::detail::ps_atom_t>
176 {
177  return encode(ldbl(value));
178 }
179 
180 template <class T> // complex
182 fhicl::detail::encode(std::complex<T> const& value)
183 {
184  return '(' + encode(value.real()) + ',' + encode(value.imag()) + ')';
185 }
186 
187 template <class T> // sequence
189 fhicl::detail::encode(std::vector<T> const& value)
190 {
192  for (auto const& e : value) {
193  result.emplace_back(encode(e));
194  }
195  return result;
196 }
197 
198 template <class T> // none of the above
201 {
202  return boost::lexical_cast<std::string>(value);
203 }
204 
205 // ----------------------------------------------------------------------
206 
207 //===================================================================
208 // unsigned
209 template <class T>
211 fhicl::detail::decode(std::any const& a, T& result)
212 {
213  std::uintmax_t via;
214  decode(a, via);
215  result = boost::numeric_cast<T>(via);
216 }
217 
218 //====================================================================
219 // signed
220 template <class T>
222 fhicl::detail::decode(std::any const& a, T& result)
223 {
224  std::intmax_t via;
225  decode(a, via);
226  result = boost::numeric_cast<T>(via);
227 }
228 
229 //====================================================================
230 // floating-point
231 template <class T>
232 std::enable_if_t<std::is_floating_point_v<T>>
233 fhicl::detail::decode(std::any const& a, T& result)
234 {
235  ldbl via;
236  decode(a, via);
237  result = via; // boost::numeric_cast<T>(via);
238 }
239 
240 //====================================================================
241 // complex
242 template <class T>
243 void
244 fhicl::detail::decode(std::any const& a, std::complex<T>& result)
245 {
246  std::complex<ldbl> via;
247  decode(a, via);
248  result = std::complex<T>{boost::numeric_cast<T>(via.real()),
249  boost::numeric_cast<T>(via.imag())};
250 }
251 
252 //====================================================================
253 // sequence
254 template <class T>
255 void
256 fhicl::detail::decode(std::any const& a, std::vector<T>& result)
257 {
258  if (a.type() == typeid(std::string)) {
261 
263  decode(a, str);
264 
265  extended_value xval;
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  sequence_t const& seq = 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 base
297 template <typename TUPLE>
298 void
300  fhicl::detail::ps_sequence_t const& vec,
301  TUPLE& result)
302 {
303  std::tuple_element_t<0, TUPLE> result_elem;
304  decode(vec.at(0), result_elem);
305  std::get<0>(result) = result_elem;
306 }
307 
308 // per-entry decode
309 template <unsigned IENTRY, typename TUPLE>
310 void
312  fhicl::detail::ps_sequence_t const& vec,
313  TUPLE& result)
314 {
315  std::tuple_element_t<IENTRY, TUPLE> result_elem;
316  decode(vec.at(IENTRY), result_elem);
317  std::get<IENTRY>(result) = result_elem;
319 }
320 
321 // tuple-type support
322 template <typename U>
323 void
325 {
326  auto const seq = std::any_cast<ps_sequence_t>(a);
327 
328  constexpr std::size_t TUPLE_SIZE = std::tuple_size_v<U>;
329 
330  if (seq.size() != TUPLE_SIZE) {
331  std::ostringstream errmsg;
332  errmsg << "Number of expected arguments (" << TUPLE_SIZE
333  << ") does not match "
334  << "number of FHiCL sequence entries (" << seq.size() << "): [ ";
335  for (auto ca = seq.begin(); ca != seq.cend(); ++ca) {
337  decode(*ca, tmp);
338  errmsg << tmp;
339  if (ca != seq.cend() - 1) {
340  errmsg << ", ";
341  }
342  }
343  errmsg << " ]";
344  throw std::length_error(errmsg.str());
345  }
346 
348 }
349 
350 //====================================================================
351 template <class T> // none of the above
353 fhicl::detail::decode(std::any const& a, T& result)
354 {
355  result = std::any_cast<T>(a);
356 }
357 
358 // ======================================================================
359 
360 #endif /* fhiclcpp_coding_h */
361 
362 // Local Variables:
363 // mode: c++
364 // End:
bool parse_value_string(std::string const &s, extended_value &v, std::string &unparsed)
Definition: parse.cc:669
static QCString result
bool is_a(value_tag const t) const noexcept
ps_atom_t encode(std::string const &)
Definition: coding.cc:87
std::string string
Definition: nybbler.cc:12
long double ldbl
Definition: coding.h:46
void decode_tuple(std::any const &, U &tuple)
Definition: coding.h:324
void decode(std::any const &, std::string &)
Definition: coding.h:142
std::vector< std::any > ps_sequence_t
Definition: coding.h:45
const double e
const double a
std::vector< extended_value > sequence_t
string tmp
Definition: languages.py:63
bool is_nil(std::any const &val)
Definition: coding.cc:75
fhicl::extended_value::sequence_t sequence_t
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
static QCString str
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool is_sequence(std::any const &val)
Definition: coding.h:49
static void decode_tuple_entry(ps_sequence_t const &, TUPLE &)
Definition: coding.h:311