xmlrpc_value_utils.hpp
Go to the documentation of this file.
1 #pragma once
2 
11 #include <array>
12 #include <limits>
13 #include <list>
14 #include <map>
15 #include <set>
16 #include <string>
17 #include <unordered_map>
18 #include <unordered_set>
19 #include <vector>
20 
21 #include <dynamic_reconfigure/BoolParameter.h>
22 #include <dynamic_reconfigure/Config.h>
23 #include <dynamic_reconfigure/DoubleParameter.h>
24 #include <dynamic_reconfigure/IntParameter.h>
25 #include <dynamic_reconfigure/StrParameter.h>
26 #include <XmlRpcValue.h>
27 #include <XmlRpcException.h>
28 
30 
31 #if !XMLRPCPP_HAS_PRINTTO
32 namespace XmlRpc
33 {
34 // This prevents GTest to understand all XmlRpcValues as structs and trying to print them as such.
35 // That results in memory corruption and an exception thrown in GTest EXPECT* methods.
36 inline void PrintTo(const XmlRpcValue& value, ::std::ostream* os)
37 {
38  if (os)
39  *os << value.toXml();
40 }
41 }
42 #endif
43 
44 namespace cras
45 {
46 
55 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::XmlRpc::XmlRpcValue& v, bool /*skipNonConvertible*/ = false,
56  ::std::list<::std::string>* errors = nullptr)
57 {
58  v = x;
59  return true;
60 }
61 
63 inline bool convert(const ::XmlRpc::XmlRpcValue& x, bool& v, bool /*skipNonConvertible*/ = false,
64  ::std::list<::std::string>* errors = nullptr)
65 {
66  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeBoolean)
67  {
68  v = x;
69  return true;
70  }
71 
72  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeInt)
73  {
74  const auto i = static_cast<int>(x);
75  if (i == 0 || i == 1)
76  {
77  v = static_cast<bool>(i);
78  return true;
79  }
80  else if (errors != nullptr)
81  errors->push_back(::cras::format("Cannot convert int value %i to boolean.", i));
82  }
83 
84  if (errors != nullptr)
85  errors->push_back(::cras::format("Cannot convert type %s to boolean.", ::cras::to_cstring(x.getType())));
86  return false;
87 }
88 
89 inline bool convert(const ::XmlRpc::XmlRpcValue& x, int& v, bool /*skipNonConvertible*/ = false,
90  ::std::list<::std::string>* errors = nullptr)
91 {
92  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeInt)
93  {
94  v = x;
95  return true;
96  }
97 
98  if (errors != nullptr)
99  errors->push_back(::cras::format("Cannot convert type %s to int.", ::cras::to_cstring(x.getType())));
100 
101  return false;
102 }
103 
104 #define DEFINE_INTEGRAL_CONVERT(resultType, xmlType, minBound, maxBound) \
105 \
106  inline bool convert(const ::XmlRpc::XmlRpcValue& x, resultType& v, bool skipNonConvertible = false, \
107  ::std::list<::std::string>* errors = nullptr) \
108  { \
109  xmlType i; \
110  if (!convert(x, i, skipNonConvertible, errors)) \
111  return false; \
112  if (i < (minBound) || i > (maxBound)) { \
113  if (errors != nullptr) \
114  errors->push_back(::cras::format("Value %s is out of bounds <%s, %s>.", \
115  ::cras::to_string(i).c_str(), ::cras::to_string(minBound).c_str(), ::cras::to_string(maxBound).c_str())); \
116  return false; \
117  } \
118  v = static_cast<resultType>(i); \
119  return true; \
120  }
121 
122 DEFINE_INTEGRAL_CONVERT(char, int, CHAR_MIN, CHAR_MAX)
123 DEFINE_INTEGRAL_CONVERT(signed char, int, CHAR_MIN, CHAR_MAX)
124 DEFINE_INTEGRAL_CONVERT(short, int, SHRT_MIN, SHRT_MAX) // NOLINT
125 DEFINE_INTEGRAL_CONVERT(long, int, LONG_MIN, LONG_MAX) // NOLINT
126 DEFINE_INTEGRAL_CONVERT(long long, int, LONG_LONG_MIN, LONG_LONG_MAX) // NOLINT
127 
128 DEFINE_INTEGRAL_CONVERT(unsigned char, int, 0, UCHAR_MAX)
129 DEFINE_INTEGRAL_CONVERT(unsigned short, int, 0, USHRT_MAX) // NOLINT
130 DEFINE_INTEGRAL_CONVERT(unsigned int, int, 0, UINT_MAX)
131 DEFINE_INTEGRAL_CONVERT(unsigned long, int, 0, ULONG_MAX) // NOLINT
132 DEFINE_INTEGRAL_CONVERT(unsigned long long, int, 0, ULONG_LONG_MAX) // NOLINT
133 
135 inline bool convert(const ::XmlRpc::XmlRpcValue& x, double& v, bool /*skipNonConvertible*/ = false,
136  ::std::list<::std::string>* errors = nullptr)
137 {
138  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeDouble)
139  {
140  v = x;
141  return true;
142  }
143 
144  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeInt)
145  {
146  v = static_cast<double>(static_cast<int>(x));
147  return true;
148  }
149 
150  if (errors != nullptr)
151  errors->push_back(::cras::format("Cannot convert type %s to double.", ::cras::to_cstring(x.getType())));
152 
153  return false;
154 }
155 
156 #define DEFINE_DOUBLE_CONVERT(resultType, xmlType, minBound, maxBound) \
157 \
158  inline bool convert(const ::XmlRpc::XmlRpcValue& x, resultType& v, bool skipNonConvertible = false, \
159  ::std::list<::std::string>* errors = nullptr) \
160  { \
161  xmlType i; \
162  if (!convert(x, i, skipNonConvertible, errors)) \
163  return false; \
164  if (::std::isnan(i)) { v = ::std::numeric_limits<resultType>::quiet_NaN(); return true; } \
165  if (::std::isinf(i) && i > 0) { v = ::std::numeric_limits<resultType>::infinity(); return true; } \
166  if (::std::isinf(i) && i < 0) { v = -::std::numeric_limits<resultType>::infinity(); return true; } \
167  if (i < (minBound) || i > (maxBound)) { \
168  if (errors != nullptr) \
169  errors->push_back(::cras::format("Value %s is out of bounds <%s, %s>.", \
170  ::cras::to_string(i).c_str(), ::cras::to_string(minBound).c_str(), ::cras::to_string(maxBound).c_str())); \
171  return false; \
172  } \
173  v = static_cast<resultType>(i); \
174  return true; \
175  }
176 
177 DEFINE_DOUBLE_CONVERT(float, double, -FLT_MAX, FLT_MAX)
178 DEFINE_DOUBLE_CONVERT(long double, double, -LDBL_MAX, LDBL_MAX)
179 
180 inline bool convert(const ::XmlRpc::XmlRpcValue& x, std::string& v, bool /*skipNonConvertible*/ = false,
182  ::std::list<::std::string>* errors = nullptr)
183 {
184  if (x.getType() == ::XmlRpc::XmlRpcValue::TypeString)
185  {
186  v = static_cast<::std::string>(x);
187  return true;
188  }
189 
190  if (errors != nullptr)
191  errors->push_back(::cras::format("Cannot convert type %s to string.", ::cras::to_cstring(x.getType())));
192 
193  return false;
194 }
195 
196 // forward-declare container types so that they can be used by the other container converters (map inside vector etc.)
198 template<typename T>
199 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::map<::std::string, T>& v,
200  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
201 
203 template<typename T>
204 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::unordered_map<::std::string, T>& v,
205  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
206 
208 template<typename T>
209 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::vector<T>& v,
210  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
211 
213 template<typename T>
214 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::list<T>& v,
215  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
216 
218 template<typename T>
219 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::set<T>& v,
220  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
221 
223 template<typename T>
224 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::unordered_set<T>& v,
225  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
226 
228 template<typename T, size_t N>
229 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::array<T, N>& v,
230  bool skipNonConvertible = false, ::std::list<::std::string>* errors = nullptr);
231 
232 #define DEFINE_ARRAY_CONVERT(arrayType, insertFn) \
233  template<typename T> \
234  inline bool convert(const ::XmlRpc::XmlRpcValue& x, arrayType<T>& v, bool skipNonConvertible, \
235  ::std::list<::std::string>* errors) \
236  { \
237  if (x.getType() != ::XmlRpc::XmlRpcValue::TypeArray) { \
238  if (errors != nullptr) \
239  errors->push_back(::cras::format("Cannot convert type %s to array.", ::cras::to_cstring(x.getType())));\
240  return false; \
241  } \
242  v.clear(); \
243  for (size_t i = 0; i < x.size(); ++i) \
244  { \
245  T t; \
246  if (convert(x[i], t, skipNonConvertible, errors)) \
247  v.insertFn(t); \
248  else if (!skipNonConvertible) \
249  return false; \
250  } \
251  return v.size() > 0 || x.size() == 0; \
252  }
253 
254 DEFINE_ARRAY_CONVERT(::std::vector, push_back)
255 DEFINE_ARRAY_CONVERT(::std::list, push_back)
256 DEFINE_ARRAY_CONVERT(::std::set, insert)
257 DEFINE_ARRAY_CONVERT(::std::unordered_set, insert)
258 
259 template<typename T, size_t N>
260 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::std::array<T, N>& v, bool skipNonConvertible,
261  ::std::list<::std::string>* errors)
262 {
263  if (x.getType() != ::XmlRpc::XmlRpcValue::TypeArray)
264  {
265  if (errors != nullptr)
266  errors->push_back(::cras::format("Cannot convert type %s to array.", ::cras::to_cstring(x.getType())));
267  return false;
268  }
269  if (x.size() != N)
270  {
271  if (errors != nullptr)
272  errors->push_back(::cras::format("The array is expected to have %zu items, but %i was given.", N, x.size()));
273  return false;
274  }
275  for (size_t i = 0; i < x.size(); ++i)
276  {
277  T t;
278  if (convert(x[i], t, skipNonConvertible, errors))
279  v[i] = t;
280  else // we cannot skip non-convertible values because we do not know what to use instead of them
281  return false;
282  }
283  return true;
284 }
285 
286 #define DEFINE_STRUCT_CONVERT(mapType) \
287  template<typename T> \
288  inline bool convert(const ::XmlRpc::XmlRpcValue& x, mapType<::std::string, T>& v, bool skipNonConvertible, \
289  ::std::list<::std::string>* errors) \
290  { \
291  if (x.getType() != ::XmlRpc::XmlRpcValue::TypeStruct) { \
292  if (errors != nullptr) \
293  errors->push_back(::cras::format("Cannot convert type %s to struct.", ::cras::to_cstring(x.getType())));\
294  return false; \
295  } \
296  v.clear(); \
297  for (auto it = x.begin(); it != x.end(); ++it) \
298  { \
299  T t; \
300  if (convert(it->second, t, skipNonConvertible, errors)) \
301  v[it->first] = t; \
302  else if (!skipNonConvertible) \
303  return false; \
304  } \
305  return v.size() > 0 || x.size() == 0; \
306  }
307 
308 DEFINE_STRUCT_CONVERT(::std::map)
309 DEFINE_STRUCT_CONVERT(::std::unordered_map)
310 
311 inline bool convert(const ::XmlRpc::XmlRpcValue& x, ::dynamic_reconfigure::Config& v, bool skipNonConvertible,
312  ::std::list<::std::string>* errors)
313 {
314  if (x.getType() != ::XmlRpc::XmlRpcValue::TypeStruct)
315  {
316  if (errors != nullptr)
317  errors->push_back(::cras::format(
318  "Cannot convert type %s to dynamic_reconfigure/Config.", ::cras::to_cstring(x.getType())));
319  return false;
320  }
321  for (auto it = x.begin(); it != x.end(); ++it)
322  {
323  const auto& name = it->first;
324  const auto& val = it->second;
325  switch (val.getType())
326  {
328  {
329  dynamic_reconfigure::BoolParameter p;
330  p.name = name;
331  p.value = static_cast<bool>(val);
332  v.bools.push_back(p);
333  break;
334  }
336  {
337  dynamic_reconfigure::IntParameter p;
338  p.name = name;
339  p.value = static_cast<int>(val);
340  v.ints.push_back(p);
341  break;
342  }
344  {
345  dynamic_reconfigure::DoubleParameter p;
346  p.name = name;
347  p.value = static_cast<double>(val);
348  v.doubles.push_back(p);
349  break;
350  }
352  {
353  dynamic_reconfigure::StrParameter p;
354  p.name = name;
355  p.value = static_cast<std::string>(val);
356  v.strs.push_back(p);
357  break;
358  }
359  default:
360  {
361  if (errors != nullptr)
362  errors->push_back(::cras::format("Field %s of type %s cannot be stored in dynamic_reconfigure/Config.",
363  name.c_str(), ::cras::to_cstring(x.getType())));
364  if (!skipNonConvertible)
365  return false;
366  }
367  }
368  }
369  return true;
370 }
371 
372 }
cras::to_cstring
constexpr const char * to_cstring(const ::XmlRpc::XmlRpcValue::Type &value)
Return a string representation of the XmlRpcValue type.
Definition: xmlrpc_value_traits.hpp:33
cras
Definition: any.hpp:15
XmlRpc::XmlRpcValue::TypeInt
TypeInt
XmlRpc
cras::format
inline ::std::string format(::std::string format,...)
Definition: string_utils.hpp:280
XmlRpc::PrintTo
void PrintTo(const XmlRpcClientForTest::ClientConnectionState &state, ::std::ostream *os)
XmlRpc::XmlRpcValue::TypeStruct
TypeStruct
XmlRpc::XmlRpcValue::TypeDouble
TypeDouble
cras::LONG_MIN
LONG_MIN
Definition: xmlrpc_value_utils.hpp:125
XmlRpc::XmlRpcValue::TypeString
TypeString
cras::DEFINE_INTEGRAL_CONVERT
DEFINE_INTEGRAL_CONVERT(short, int, SHRT_MIN, SHRT_MAX) DEFINE_INTEGRAL_CONVERT(long
XmlRpcValue.h
XmlRpc::XmlRpcValue::TypeArray
TypeArray
DEFINE_ARRAY_CONVERT
#define DEFINE_ARRAY_CONVERT(arrayType, insertFn)
Definition: xmlrpc_value_utils.hpp:232
DEFINE_STRUCT_CONVERT
#define DEFINE_STRUCT_CONVERT(mapType)
Definition: xmlrpc_value_utils.hpp:286
DEFINE_DOUBLE_CONVERT
#define DEFINE_DOUBLE_CONVERT(resultType, xmlType, minBound, maxBound)
Definition: xmlrpc_value_utils.hpp:156
std
xmlrpc_value_traits.hpp
Various type traits for XmlRpcValue.
XmlRpcException.h
XmlRpc::XmlRpcValue::TypeBoolean
TypeBoolean
t
geometry_msgs::TransformStamped t
XmlRpc::XmlRpcValue
cras::convert
bool convert(const ::XmlRpc::XmlRpcValue &x, ::XmlRpc::XmlRpcValue &v, bool=false, ::std::list<::std::string > *errors=nullptr)
Convert XmlRpcValue x to value v.
Definition: xmlrpc_value_utils.hpp:55


cras_cpp_common
Author(s): Martin Pecka
autogenerated on Tue Nov 26 2024 03:49:04