LArSoft  v06_85_00
Liquid Argon Software toolkit - http://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::any;
23 using boost::any_cast;
24 using boost::lexical_cast;
25 using boost::numeric_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 #if 0
67  if( result.size() >= 2 && result[0] == '\"' && result.end()[-1] == '\"' )
68  result = cet::unescape( result.substr(1, result.size()-2) );
69 #endif // 0
70 }
71 
72 // ----------------------------------------------------------------------
73 
74 bool
75 fhicl::detail::is_nil(boost::any const& val)
76 {
77  bool result = false;
78  if (!(is_table(val) || is_sequence(val))) {
79  std::string str;
80  atom_rep(val, str);
81  result = (str == canon_nil());
82  }
83  return result;
84 }
85 
86 ps_atom_t // string (with quotes)
87 fhicl::detail::encode(std::string const& value)
88 {
89  bool is_quoted = value.size() >= 2 && value[0] == value.end()[-1] &&
90  (value[0] == '\"' || value[0] == '\'');
91 
92  std::string const& str = is_quoted ? value : '\'' + value + '\'';
93 
94  extended_value xval;
95  std::string unparsed;
96  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(STRING))
97  throw fhicl::exception(type_mismatch, "error in input string:\n")
98  << str << "\nat or before:\n"
99  << unparsed;
100 
101  return extended_value::atom_t(xval);
102 }
103 
104 ps_atom_t // string (with quotes)
106 {
107  return encode(std::string(value));
108 }
109 
110 ps_atom_t // nil
112 {
113  return canon_nil();
114 }
115 
116 ps_atom_t // bool
118 {
119  return value ? literal_true() : literal_false();
120 }
121 
122 ParameterSetID // table
124 {
125  return ParameterSetRegistry::put(value);
126 }
127 
128 ps_atom_t // unsigned
130 {
131  std::string result = lexical_cast<std::string>(value);
132  if (result.size() > 6) {
133  std::size_t sz = result.size() - 1;
134  result.insert(1, ".");
135  result += "e+" + lexical_cast<std::string>(sz);
136  }
137  return result;
138 }
139 
140 ps_atom_t // signed
142 {
143  std::string result = encode(std::uintmax_t(std::abs(value)));
144  if (value < 0)
145  result.insert(0, "-");
146  return result;
147 }
148 
149 ps_atom_t // floating-point
151 {
152  if (value == std::numeric_limits<ldbl>::infinity())
153  return '+' + literal_infinity();
154  if (value == -std::numeric_limits<ldbl>::infinity())
155  return '-' + literal_infinity();
156 
157  std::intmax_t chopped = static_cast<std::intmax_t>(value);
158  if (static_cast<ldbl>(chopped) == value)
159  return encode(chopped);
160 
161  std::string result;
162  cet::canonical_number(lexical_cast<std::string>(value), result);
163  return result;
164 }
165 
166 // ----------------------------------------------------------------------
167 
168 void // string without delimiting quotes
169 fhicl::detail::decode(any const& a, std::string& result)
170 {
171  atom_rep(a, result);
172  if (result == canon_nil())
173  throw fhicl::exception(type_mismatch, "can't obtain string from nil");
174 
175  if (result.size() >= 2 && result[0] == '\"' && result.end()[-1] == '\"')
176  result = cet::unescape(result.substr(1, result.size() - 2));
177 }
178 
179 void // nil
180 fhicl::detail::decode(any const& a, void*& result)
181 {
182  std::string str;
183  atom_rep(a, str);
184 
185  if (str != canon_nil())
186  throw fhicl::exception(type_mismatch, "error in nil string:\n") << str;
187 
188  result = 0;
189 }
190 
191 void // bool
192 fhicl::detail::decode(any const& a, bool& result)
193 {
194  std::string str;
195  decode(a, str);
196 
197  extended_value xval;
198  std::string unparsed;
199  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(BOOL))
200  throw fhicl::exception(type_mismatch, "error in bool string:\n")
201  << str << "\nat or before:\n"
202  << unparsed;
203 
205  atom_t const& atom = atom_t(xval);
206  result = atom == literal_true();
207 }
208 
209 void // table
210 fhicl::detail::decode(any const& a, ParameterSet& result)
211 {
212  ParameterSetID id = any_cast<ParameterSetID>(a);
213  result = ParameterSetRegistry::get(id);
214 }
215 
216 void // unsigned
217 fhicl::detail::decode(any const& a, std::uintmax_t& result)
218 {
219  std::string str;
220  decode(a, str);
221 
222  extended_value xval;
223  std::string unparsed;
224  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
225  throw fhicl::exception(type_mismatch, "error in unsigned string:\n")
226  << str << "\nat or before:\n"
227  << unparsed;
228 
230  atom_t const& atom = atom_t(xval);
231  ldbl via = lexical_cast<ldbl>(atom);
232  result = numeric_cast<std::uintmax_t>(via);
233  if (via != ldbl(result))
234  throw std::range_error("narrowing conversion");
235 }
236 
237 void // signed
238 fhicl::detail::decode(any const& a, std::intmax_t& result)
239 {
240  std::string str;
241  decode(a, str);
242 
243  extended_value xval;
244  std::string unparsed;
245  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
246  throw fhicl::exception(type_mismatch, "error in signed string:\n")
247  << str << "\nat or before:\n"
248  << unparsed;
249 
251  atom_t const& atom = atom_t(xval);
252  ldbl via = lexical_cast<ldbl>(atom);
253  result = numeric_cast<std::intmax_t>(via);
254  if (via != ldbl(result))
255  throw std::range_error("narrowing conversion");
256 }
257 
258 void // floating-point
259 fhicl::detail::decode(any const& a, ldbl& result)
260 {
261  std::string str;
262  decode(a, str);
263 
264  extended_value xval;
265  std::string unparsed;
266  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(NUMBER))
267  throw fhicl::exception(type_mismatch, "error in float string:\n")
268  << str << "\nat or before:\n"
269  << unparsed;
270 
272  atom_t const& atom = atom_t(xval);
273  if (atom.substr(1) == literal_infinity()) {
274  switch (atom[0]) {
275  case '+':
276  result = +std::numeric_limits<ldbl>::infinity();
277  return;
278  case '-':
279  result = -std::numeric_limits<ldbl>::infinity();
280  return;
281  }
282  } else
283  result = lexical_cast<ldbl>(atom);
284 }
285 
286 void // complex
287 fhicl::detail::decode(any const& a, std::complex<ldbl>& result)
288 {
289  std::string str;
290  decode(a, str);
291 
292  extended_value xval;
293  std::string unparsed;
294  if (!parse_value_string(str, xval, unparsed) || !xval.is_a(COMPLEX))
295  throw fhicl::exception(type_mismatch, "error in complex string:\n")
296  << str << "\nat or before:\n"
297  << unparsed;
298 
300  complex_t const& cmplx = complex_t(xval);
301  ldbl real, imag;
302  decode(cmplx.first, real);
303  decode(cmplx.second, imag);
304  result = std::complex<ldbl>(real, imag);
305 }
306 
307 // ======================================================================
intermediate_table::complex_t complex_t
void decode(boost::any const &, std::string &)
static ParameterSetID const & put(ParameterSet const &ps)
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
static ps_atom_t literal_false()
Definition: coding.cc:44
bool is_nil(boost::any const &val)
Definition: coding.cc:75
static collection_type const & get() noexcept
bool is_sequence(boost::any const &val)
Definition: coding.h:50
bool is_table(boost::any const &val)
Definition: coding.h:56
std::pair< std::string, std::string > complex_t
static ps_atom_t literal_true()
Definition: coding.cc:37
parameter set interface
bool is_a(value_tag t) const
static std::string canon_nil()
Definition: coding.cc:30
static ps_atom_t literal_infinity()
Definition: coding.cc:51
intermediate_table::atom_t atom_t
std::string value(boost::any const &)
static void atom_rep(any const &a, std::string &result)
Definition: coding.cc:58
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