LArSoft  v06_85_00
Liquid Argon Software toolkit - http://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/any.hpp"
24 #include "boost/lexical_cast.hpp"
25 #include "boost/numeric/conversion/cast.hpp"
26 #include "cetlib_except/demangle.h"
28 #include "fhiclcpp/exception.h"
30 #include "fhiclcpp/fwd.h"
31 #include "fhiclcpp/parse.h"
32 #include "fhiclcpp/type_traits.h"
33 
34 #include <array>
35 #include <complex>
36 #include <cstdint>
37 #include <sstream>
38 #include <string>
39 #include <tuple>
40 #include <utility>
41 #include <vector>
42 
43 namespace fhicl {
44  namespace detail {
45  typedef std::string ps_atom_t;
46  typedef std::vector<boost::any> ps_sequence_t;
47  typedef long double ldbl;
48 
49  inline bool
50  is_sequence(boost::any const& val)
51  {
52  return val.type() == typeid(ps_sequence_t);
53  }
54 
55  inline bool
56  is_table(boost::any const& val)
57  {
58  return val.type() == typeid(ParameterSetID);
59  }
60 
61  bool is_nil(boost::any const& val);
62 
63  // ----------------------------------------------------------------------
64 
65  ps_atom_t encode(std::string const&); // string (w/ quotes)
66  ps_atom_t encode(char const*); // string (w/ quotes)
67  ps_atom_t encode(void*); // nil
68  ps_atom_t encode(bool); // bool
69  ParameterSetID encode(ParameterSet const&); // table
70  ps_atom_t encode(std::uintmax_t); // unsigned
71  template <class T>
72  typename tt::enable_if<tt::is_uint<T>::value, ps_atom_t>::type encode(
73  T const&); // unsigned
74  ps_atom_t encode(std::intmax_t); // signed
75  template <class T>
76  typename tt::enable_if<tt::is_int<T>::value, ps_atom_t>::type encode(
77  T const&); // signed
78  ps_atom_t encode(ldbl); // floating-point
79  template <class T>
80  typename tt::enable_if<tt::is_floating_point<T>::value, ps_atom_t>::type
81  encode(T const&); // floating-point
82  template <class T>
83  ps_atom_t encode(std::complex<T> const&); // complex
84  template <class T>
85  ps_sequence_t encode(std::vector<T> const&); // sequence
86  template <class T>
87  typename tt::disable_if<tt::is_numeric<T>::value, std::string>::type encode(
88  T const&); // none of the above
89 
90  // ----------------------------------------------------------------------
91 
92  void decode(boost::any const&, std::string&); // string
93  void decode(boost::any const&, void*&); // nil
94  void decode(boost::any const&, bool&); // bool
95  void decode(boost::any const&, ParameterSet&); // table
96  void decode(boost::any const&, std::uintmax_t&); // unsigned
97 
98  template <class T>
99  typename tt::enable_if<tt::is_uint<T>::value, void>::type decode(
100  boost::any const&,
101  T&); // unsigned
102 
103  void decode(boost::any const&, std::intmax_t&); // signed
104 
105  template <class T>
106  typename tt::enable_if<tt::is_int<T>::value, void>::type decode(
107  boost::any const&,
108  T&); // signed
109 
110  void decode(boost::any const&, ldbl&); // floating-point
111 
112  template <class T>
114  boost::any const&,
115  T&); // floating-point
116 
117  void decode(boost::any const&, std::complex<ldbl>&); // complex
118 
119  template <class T>
120  void decode(boost::any const&, std::complex<T>&); // complex
121 
122  template <class T>
123  void decode(boost::any const&, std::vector<T>&); // sequence
124 
125  template <typename U>
126  void decode_tuple(boost::any const&, U& tuple); // tuple-type decoding
127 
128  template <typename T, std::size_t SIZE>
129  void decode(boost::any const& a, std::array<T, SIZE>& result) // std::array
130  {
131  decode_tuple(a, result);
132  }
133 
134  template <typename KEY, typename VALUE>
135  void decode(boost::any const& a, std::pair<KEY, VALUE>& result) // std::pair
136  {
137  decode_tuple(a, result);
138  }
139 
140  template <typename... ARGS>
141  void decode(boost::any const& a, std::tuple<ARGS...>& result) // std::tuple
142  {
143  decode_tuple(a, result);
144  }
145 
146  template <unsigned SIZE, typename TUPLE> // tuple support
147  struct per_entry {
148  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
149  };
150 
151  template <typename TUPLE> // tuple support
152  struct per_entry<0, TUPLE> {
153  static void decode_tuple_entry(ps_sequence_t const&, TUPLE&);
154  };
155 
156  template <class T>
157  typename tt::disable_if<tt::is_numeric<T>::value, void>::type decode(
158  boost::any const&,
159  T&); // none of the above
160 
161  } // fhicl::detail
162 } // fhicl
163 
164 // ======================================================================
165 
166 template <class T> // unsigned
169 {
170  return encode(uintmax_t(value));
171 }
172 
173 template <class T> // signed
176 {
177  return encode(intmax_t(value));
178 }
179 
180 template <class T> // floating-point
184 {
185  return encode(ldbl(value));
186 }
187 
188 template <class T> // complex
190 fhicl::detail::encode(std::complex<T> const& value)
191 {
192  return '(' + encode(value.real()) + ',' + encode(value.imag()) + ')';
193 }
194 
195 template <class T> // sequence
197 fhicl::detail::encode(std::vector<T> const& value)
198 {
199  ps_sequence_t result;
200  for (typename std::vector<T>::const_iterator it = value.begin(),
201  e = value.end();
202  it != e;
203  ++it) {
204  result.push_back(boost::any(encode(*it)));
205  }
206  return result;
207 }
208 
209 template <class T> // none of the above
210 typename tt::disable_if<tt::is_numeric<T>::value, std::string>::type
211 fhicl::detail::encode(T const& value)
212 {
213  return boost::lexical_cast<std::string>(value);
214 }
215 
216 // ----------------------------------------------------------------------
217 
218 //===================================================================
219 // unsigned
220 template <class T>
221 typename tt::enable_if<tt::is_uint<T>::value, void>::type
222 fhicl::detail::decode(boost::any const& a, T& result)
223 {
224  std::uintmax_t via;
225  decode(a, via);
226  result = boost::numeric_cast<T>(via);
227 }
228 
229 //====================================================================
230 // signed
231 template <class T>
232 typename tt::enable_if<tt::is_int<T>::value, void>::type
233 fhicl::detail::decode(boost::any const& a, T& result)
234 {
235  std::intmax_t via;
236  decode(a, via);
237  result = boost::numeric_cast<T>(via);
238 }
239 
240 //====================================================================
241 // floating-point
242 template <class T>
244 fhicl::detail::decode(boost::any const& a, T& result)
245 {
246  ldbl via;
247  decode(a, via);
248  result = via; // boost::numeric_cast<T>(via);
249 }
250 
251 //====================================================================
252 // complex
253 template <class T>
254 void
255 fhicl::detail::decode(boost::any const& a, std::complex<T>& result)
256 {
257  std::complex<ldbl> via;
258  decode(a, via);
259  result = std::complex<T>(boost::numeric_cast<T>(via.real()),
260  boost::numeric_cast<T>(via.imag()));
261 }
262 
263 //====================================================================
264 // sequence
265 template <class T>
266 void
267 fhicl::detail::decode(boost::any const& a, std::vector<T>& result)
268 {
269  if (a.type() == typeid(std::string)) {
272 
273  std::string str;
274  decode(a, str);
275 
276  extended_value xval;
277  std::string unparsed;
278  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(SEQUENCE))
279  throw fhicl::exception(type_mismatch, "error in sequence string:\n")
280  << str << "\nat or before:\n"
281  << unparsed;
282 
283  sequence_t const& seq = sequence_t(xval);
284  result.clear();
285  T via;
286  for (sequence_t::const_iterator it = seq.begin(), e = seq.end(); it != e;
287  ++it) {
288  decode(it->to_string(), via);
289  result.push_back(via);
290  }
291  }
292 
293  else if (a.type() == typeid(ps_sequence_t)) {
294  ps_sequence_t const& seq = boost::any_cast<ps_sequence_t>(a);
295  result.clear();
296  T via;
297  for (ps_sequence_t::const_iterator it = seq.begin(), e = seq.end(); it != e;
298  ++it) {
299  decode(*it, via);
300  result.push_back(via);
301  }
302  }
303 
304  else
305  throw fhicl::exception(type_mismatch, "invalid sequence");
306 }
307 
308 //====================================================================
309 // per-entry decode base
310 template <typename TUPLE>
311 void
313  fhicl::detail::ps_sequence_t const& vec,
314  TUPLE& result)
315 {
316  std::tuple_element_t<0, TUPLE> result_elem;
317  decode(vec.at(0), result_elem);
318  std::get<0>(result) = result_elem;
319 }
320 
321 // per-entry decode
322 template <unsigned IENTRY, typename TUPLE>
323 void
325  fhicl::detail::ps_sequence_t const& vec,
326  TUPLE& result)
327 {
328  std::tuple_element_t<IENTRY, TUPLE> result_elem;
329  decode(vec.at(IENTRY), result_elem);
330  std::get<IENTRY>(result) = result_elem;
332 }
333 
334 // tuple-type support
335 template <typename U>
336 void
337 fhicl::detail::decode_tuple(boost::any const& a, U& result)
338 {
339  ps_sequence_t const& seq = boost::any_cast<ps_sequence_t>(a);
340 
341  constexpr std::size_t TUPLE_SIZE = std::tuple_size<U>::value;
342 
343  if (seq.size() != TUPLE_SIZE) {
344  std::ostringstream errmsg;
345  errmsg << "Number of expected arguments (" << TUPLE_SIZE
346  << ") does not match "
347  << "number of FHiCL sequence entries (" << seq.size() << "): [ ";
348  for (auto ca = seq.begin(); ca != seq.cend(); ++ca) {
349  std::string tmp;
350  decode(*ca, tmp);
351  errmsg << tmp;
352  if (ca != seq.cend() - 1) {
353  errmsg << ", ";
354  }
355  }
356  errmsg << " ]";
357  throw std::length_error(errmsg.str());
358  }
359 
361 }
362 
363 //====================================================================
364 template <class T> // none of the above
365 typename tt::disable_if<tt::is_numeric<T>::value, void>::type
366 fhicl::detail::decode(boost::any const& a, T& result)
367 {
368  result = boost::any_cast<T>(a);
369 }
370 
371  // ======================================================================
372 
373 #endif /* fhiclcpp_coding_h */
374 
375 // Local Variables:
376 // mode: c++
377 // End:
void decode(boost::any const &, std::string &)
bool parse_value_string(std::string const &s, extended_value &v, std::string &unparsed)
Definition: parse.cc:802
ps_atom_t encode(std::string const &)
Definition: coding.cc:87
bool is_nil(boost::any const &val)
Definition: coding.cc:75
bool is_sequence(boost::any const &val)
Definition: coding.h:50
Float_t tmp
Definition: plot.C:37
bool is_table(boost::any const &val)
Definition: coding.h:56
Definition: coding.h:147
intermediate_table::const_iterator const_iterator
parameter set interface
std::vector< extended_value > sequence_t
bool is_a(value_tag t) const
void decode_tuple(boost::any const &, U &tuple)
Definition: coding.h:337
fhicl::extended_value::sequence_t sequence_t
std::enable_if<!b, T > disable_if
Definition: type_traits.h:63
std::string value(boost::any const &)
Float_t e
Definition: plot.C:34
long double ldbl
Definition: coding.h:47
std::string ps_atom_t
Definition: coding.h:45
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::vector< boost::any > ps_sequence_t
Definition: coding.h:46
static void decode_tuple_entry(ps_sequence_t const &, TUPLE &)
Definition: coding.h:324