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


cras_cpp_common
Author(s): Martin Pecka
autogenerated on Sun Jan 14 2024 03:48:14