LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
coding.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // coding
4 //
5 // ======================================================================
6 
7 #include "fhiclcpp/coding.h"
8 
9 #include "cetlib/canonical_number.h"
10 #include "cetlib/canonical_string.h"
11 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <cstddef>
15 #include <cstdlib>
16 #include <limits>
17 #include <stdexcept>
18 
19 using namespace fhicl;
20 using namespace fhicl::detail;
21 
22 using boost::lexical_cast;
23 using boost::numeric_cast;
24 using std::any;
25 using std::any_cast;
26 
27 // ======================================================================
28 
29 static inline std::string
31 {
32  static std::string const canon_nil(9, '\0');
33  return canon_nil;
34 }
35 
36 static inline ps_atom_t
38 {
39  static std::string literal_true("true");
40  return literal_true;
41 }
42 
43 static inline ps_atom_t
45 {
46  static std::string literal_false("false");
47  return literal_false;
48 }
49 
50 static inline ps_atom_t
52 {
53  static std::string literal_infinity("infinity");
54  return literal_infinity;
55 }
56 
57 static void
58 atom_rep(any const& a, std::string& result)
59 {
60  if (is_table(a))
61  throw fhicl::exception(type_mismatch, "can't obtain atom from table");
62  if (is_sequence(a))
63  throw fhicl::exception(type_mismatch, "can't obtain atom from sequence");
64 
65  result = any_cast<std::string>(a);
66 }
67 
68 // ----------------------------------------------------------------------
69 
70 bool
71 fhicl::detail::is_nil(std::any const& val)
72 {
73  bool result = false;
74  if (!(is_table(val) || is_sequence(val))) {
75  std::string str;
76  atom_rep(val, str);
77  result = (str == canon_nil());
78  }
79  return result;
80 }
81 
82 ps_atom_t // string (with quotes)
83 fhicl::detail::encode(std::string const& value)
84 {
85  bool is_quoted = value.size() >= 2 && value[0] == value.end()[-1] &&
86  (value[0] == '\"' || value[0] == '\'');
87 
88  std::string const& str = is_quoted ? value : '\'' + value + '\'';
89 
90  extended_value xval;
91  std::string unparsed;
92  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(STRING))
93  throw fhicl::exception(type_mismatch, "error in input string:\n")
94  << str << "\nat or before:\n"
95  << unparsed;
96 
97  return extended_value::atom_t(xval);
98 }
99 
100 ps_atom_t // string (with quotes)
102 {
103  return encode(std::string(value));
104 }
105 
106 ps_atom_t // nil
107 fhicl::detail::encode(std::nullptr_t)
108 {
109  return canon_nil();
110 }
111 
112 ps_atom_t // bool
114 {
115  return value ? literal_true() : literal_false();
116 }
117 
118 ParameterSetID // table
120 {
121  return ParameterSetRegistry::put(value);
122 }
123 
124 ps_atom_t // unsigned
126 {
127  std::string result = lexical_cast<std::string>(value);
128  if (result.size() > 6) {
129  std::size_t sz = result.size() - 1;
130  result.insert(1, ".");
131  result += "e+" + lexical_cast<std::string>(sz);
132  }
133  return result;
134 }
135 
136 ps_atom_t // signed
138 {
139  std::string result = encode(std::uintmax_t(std::abs(value)));
140  if (value < 0)
141  result.insert(0, "-");
142  return result;
143 }
144 
145 ps_atom_t // floating-point
147 {
148  if (value == std::numeric_limits<ldbl>::infinity())
149  return '+' + literal_infinity();
150  if (value == -std::numeric_limits<ldbl>::infinity())
151  return '-' + literal_infinity();
152 
153  std::intmax_t chopped = static_cast<std::intmax_t>(value);
154  if (static_cast<ldbl>(chopped) == value)
155  return encode(chopped);
156 
157  std::string result;
158  cet::canonical_number(lexical_cast<std::string>(value), result);
159  return result;
160 }
161 
162 // ----------------------------------------------------------------------
163 
164 void // string without delimiting quotes
165 fhicl::detail::decode(any const& a, std::string& result)
166 {
167  atom_rep(a, result);
168  if (result == canon_nil())
169  throw fhicl::exception(type_mismatch, "can't obtain string from nil");
170 
171  if (result.size() >= 2 && result[0] == '\"' && result.end()[-1] == '\"')
172  result = cet::unescape(result.substr(1, result.size() - 2));
173 }
174 
175 void // nil
176 fhicl::detail::decode(any const& a, std::nullptr_t& result)
177 {
178  std::string str;
179  atom_rep(a, str);
180 
181  if (str != canon_nil())
182  throw fhicl::exception(type_mismatch, "error in nil string:\n") << str;
183 
184  result = nullptr;
185 }
186 
187 void // bool
188 fhicl::detail::decode(any const& a, bool& result)
189 {
190  std::string str;
191  decode(a, str);
192 
193  extended_value xval;
194  std::string unparsed;
195  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(BOOL))
196  throw fhicl::exception(type_mismatch, "error in bool string:\n")
197  << str << "\nat or before:\n"
198  << unparsed;
199 
200  auto const& atom = extended_value::atom_t(xval);
201  result = atom == literal_true();
202 }
203 
204 void // table
205 fhicl::detail::decode(any const& a, ParameterSet& result)
206 {
207  auto const id = any_cast<ParameterSetID>(a);
208  result = ParameterSetRegistry::get(id);
209 }
210 
211 void // unsigned
212 fhicl::detail::decode(any const& a, std::uintmax_t& result)
213 {
214  std::string str;
215  decode(a, str);
216 
217  extended_value xval;
218  std::string unparsed;
219  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
220  throw fhicl::exception(type_mismatch, "error in unsigned string:\n")
221  << str << "\nat or before:\n"
222  << unparsed;
223 
224  auto const& atom = extended_value::atom_t(xval);
225  ldbl via = lexical_cast<ldbl>(atom);
226  result = numeric_cast<std::uintmax_t>(via);
227  if (via != ldbl(result))
228  throw std::range_error("narrowing conversion");
229 }
230 
231 void // signed
232 fhicl::detail::decode(any const& a, std::intmax_t& result)
233 {
234  std::string str;
235  decode(a, str);
236 
237  extended_value xval;
238  std::string unparsed;
239  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
240  throw fhicl::exception(type_mismatch, "error in signed string:\n")
241  << str << "\nat or before:\n"
242  << unparsed;
243 
244  auto const& atom = extended_value::atom_t(xval);
245  ldbl via = lexical_cast<ldbl>(atom);
246  result = numeric_cast<std::intmax_t>(via);
247  if (via != ldbl(result))
248  throw std::range_error("narrowing conversion");
249 }
250 
251 void // floating-point
252 fhicl::detail::decode(any const& a, ldbl& result)
253 {
254  std::string str;
255  decode(a, str);
256 
257  extended_value xval;
258  std::string unparsed;
259  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
260  throw fhicl::exception(type_mismatch, "error in float string:\n")
261  << str << "\nat or before:\n"
262  << unparsed;
263 
264  auto const& atom = extended_value::atom_t(xval);
265  if (atom.substr(1) == literal_infinity()) {
266  switch (atom[0]) {
267  case '+':
268  result = +std::numeric_limits<ldbl>::infinity();
269  return;
270  case '-':
271  result = -std::numeric_limits<ldbl>::infinity();
272  return;
273  }
274  } else
275  result = lexical_cast<ldbl>(atom);
276 }
277 
278 void // complex
279 fhicl::detail::decode(any const& a, std::complex<ldbl>& result)
280 {
281  std::string str;
282  decode(a, str);
283 
284  extended_value xval;
285  std::string unparsed;
286  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(COMPLEX))
287  throw fhicl::exception(type_mismatch, "error in complex string:\n")
288  << str << "\nat or before:\n"
289  << unparsed;
290 
291  auto const& cmplx = extended_value::complex_t(xval);
292  ldbl real, imag;
293  decode(cmplx.first, real);
294  decode(cmplx.second, imag);
295  result = {real, imag};
296 }
297 
298 // ======================================================================
static ParameterSetID const & put(ParameterSet const &ps)
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
static ps_atom_t literal_false()
Definition: coding.cc:44
long double ldbl
Definition: coding.h:46
static collection_type const & get() noexcept
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::pair< std::string, std::string > complex_t
void decode(std::any const &, std::string &)
static ps_atom_t literal_true()
Definition: coding.cc:37
parameter set interface
bool is_nil(std::any const &val)
Definition: coding.cc:71
static std::string canon_nil()
Definition: coding.cc:30
double value
Definition: spectrum.C:18
static ps_atom_t literal_infinity()
Definition: coding.cc:51
std::string ps_atom_t
Definition: coding.h:44
static void atom_rep(any const &a, std::string &result)
Definition: coding.cc:58
bool is_table(std::any const &val)
Definition: coding.h:55
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool is_sequence(std::any const &val)
Definition: coding.h:49