Free Electron
convert.h
1 #ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
2 #define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
3 
4 #if defined(_MSC_VER) || \
5  (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
6  (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
7 #pragma once
8 #endif
9 
10 #include <array>
11 #include <cmath>
12 #include <limits>
13 #include <list>
14 #include <map>
15 #include <unordered_map>
16 #include <sstream>
17 #include <type_traits>
18 #include <valarray>
19 #include <vector>
20 
21 #include "yaml-cpp/binary.h"
22 #include "yaml-cpp/node/impl.h"
23 #include "yaml-cpp/node/iterator.h"
24 #include "yaml-cpp/node/node.h"
25 #include "yaml-cpp/node/type.h"
26 #include "yaml-cpp/null.h"
27 
28 
29 namespace YAML {
30 class Binary;
31 struct _Null;
32 template <typename T>
33 struct convert;
34 } // namespace YAML
35 
36 namespace YAML {
37 namespace conversion {
38 inline bool IsInfinity(const std::string& input) {
39  return input == ".inf" || input == ".Inf" || input == ".INF" ||
40  input == "+.inf" || input == "+.Inf" || input == "+.INF";
41 }
42 
43 inline bool IsNegativeInfinity(const std::string& input) {
44  return input == "-.inf" || input == "-.Inf" || input == "-.INF";
45 }
46 
47 inline bool IsNaN(const std::string& input) {
48  return input == ".nan" || input == ".NaN" || input == ".NAN";
49 }
50 }
51 
52 // Node
53 template <>
54 struct convert<Node> {
55  static Node encode(const Node& rhs) { return rhs; }
56 
57  static bool decode(const Node& node, Node& rhs) {
58  rhs.reset(node);
59  return true;
60  }
61 };
62 
63 // std::string
64 template <>
65 struct convert<std::string> {
66  static Node encode(const std::string& rhs) { return Node(rhs); }
67 
68  static bool decode(const Node& node, std::string& rhs) {
69  if (!node.IsScalar())
70  return false;
71  rhs = node.Scalar();
72  return true;
73  }
74 };
75 
76 // C-strings can only be encoded
77 template <>
78 struct convert<const char*> {
79  static Node encode(const char* rhs) { return Node(rhs); }
80 };
81 
82 template <>
83 struct convert<char*> {
84  static Node encode(const char* rhs) { return Node(rhs); }
85 };
86 
87 template <std::size_t N>
88 struct convert<char[N]> {
89  static Node encode(const char* rhs) { return Node(rhs); }
90 };
91 
92 template <>
93 struct convert<_Null> {
94  static Node encode(const _Null& /* rhs */) { return Node(); }
95 
96  static bool decode(const Node& node, _Null& /* rhs */) {
97  return node.IsNull();
98  }
99 };
100 
101 namespace conversion {
102 template <typename T>
103 typename std::enable_if< std::is_floating_point<T>::value, void>::type
104 inner_encode(const T& rhs, std::stringstream& stream){
105  if (std::isnan(rhs)) {
106  stream << ".nan";
107  } else if (std::isinf(rhs)) {
108  if (std::signbit(rhs)) {
109  stream << "-.inf";
110  } else {
111  stream << ".inf";
112  }
113  } else {
114  stream << rhs;
115  }
116 }
117 
118 template <typename T>
119 typename std::enable_if<!std::is_floating_point<T>::value, void>::type
120 inner_encode(const T& rhs, std::stringstream& stream){
121  stream << rhs;
122 }
123 
124 template <typename T>
125 typename std::enable_if<(std::is_same<T, unsigned char>::value ||
126  std::is_same<T, signed char>::value), bool>::type
127 ConvertStreamTo(std::stringstream& stream, T& rhs) {
128  int num;
129  if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
130  if (num >= (std::numeric_limits<T>::min)() &&
131  num <= (std::numeric_limits<T>::max)()) {
132  rhs = static_cast<T>(num);
133  return true;
134  }
135  }
136  return false;
137 }
138 
139 template <typename T>
140 typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
141  std::is_same<T, signed char>::value), bool>::type
142 ConvertStreamTo(std::stringstream& stream, T& rhs) {
143  if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
144  return true;
145  }
146  return false;
147 }
148 }
149 
150 #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
151  template <> \
152  struct convert<type> { \
153  \
154  static Node encode(const type& rhs) { \
155  std::stringstream stream; \
156  stream.precision(std::numeric_limits<type>::max_digits10); \
157  conversion::inner_encode(rhs, stream); \
158  return Node(stream.str()); \
159  } \
160  \
161  static bool decode(const Node& node, type& rhs) { \
162  if (node.Type() != NodeType::Scalar) { \
163  return false; \
164  } \
165  const std::string& input = node.Scalar(); \
166  std::stringstream stream(input); \
167  stream.unsetf(std::ios::dec); \
168  if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
169  return false; \
170  } \
171  if (conversion::ConvertStreamTo(stream, rhs)) { \
172  return true; \
173  } \
174  if (std::numeric_limits<type>::has_infinity) { \
175  if (conversion::IsInfinity(input)) { \
176  rhs = std::numeric_limits<type>::infinity(); \
177  return true; \
178  } else if (conversion::IsNegativeInfinity(input)) { \
179  rhs = negative_op std::numeric_limits<type>::infinity(); \
180  return true; \
181  } \
182  } \
183  \
184  if (std::numeric_limits<type>::has_quiet_NaN) { \
185  if (conversion::IsNaN(input)) { \
186  rhs = std::numeric_limits<type>::quiet_NaN(); \
187  return true; \
188  } \
189  } \
190  \
191  return false; \
192  } \
193  }
194 
195 #define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
196  YAML_DEFINE_CONVERT_STREAMABLE(type, -)
197 
198 #define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
199  YAML_DEFINE_CONVERT_STREAMABLE(type, +)
200 
201 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
202 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
203 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
204 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
205 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
206 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
207 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
208 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
209 
210 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
211 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
212 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
213 
214 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
215 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
216 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
217 
218 #undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
219 #undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
220 #undef YAML_DEFINE_CONVERT_STREAMABLE
221 
222 // bool
223 template <>
224 struct convert<bool> {
225  static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
226 
227  YAML_CPP_API static bool decode(const Node& node, bool& rhs);
228 };
229 
230 // std::map
231 template <typename K, typename V, typename C, typename A>
232 struct convert<std::map<K, V, C, A>> {
233  static Node encode(const std::map<K, V, C, A>& rhs) {
234  Node node(NodeType::Map);
235  for (const auto& element : rhs)
236  node.force_insert(element.first, element.second);
237  return node;
238  }
239 
240  static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
241  if (!node.IsMap())
242  return false;
243 
244  rhs.clear();
245  for (const auto& element : node)
246 #if defined(__GNUC__) && __GNUC__ < 4
247  // workaround for GCC 3:
248  rhs[element.first.template as<K>()] = element.second.template as<V>();
249 #else
250  rhs[element.first.as<K>()] = element.second.as<V>();
251 #endif
252  return true;
253  }
254 };
255 
256 // std::unordered_map
257 template <typename K, typename V, typename H, typename P, typename A>
258 struct convert<std::unordered_map<K, V, H, P, A>> {
259  static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
260  Node node(NodeType::Map);
261  for (const auto& element : rhs)
262  node.force_insert(element.first, element.second);
263  return node;
264  }
265 
266  static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
267  if (!node.IsMap())
268  return false;
269 
270  rhs.clear();
271  for (const auto& element : node)
272 #if defined(__GNUC__) && __GNUC__ < 4
273  // workaround for GCC 3:
274  rhs[element.first.template as<K>()] = element.second.template as<V>();
275 #else
276  rhs[element.first.as<K>()] = element.second.as<V>();
277 #endif
278  return true;
279  }
280 };
281 
282 // std::vector
283 template <typename T, typename A>
284 struct convert<std::vector<T, A>> {
285  static Node encode(const std::vector<T, A>& rhs) {
286  Node node(NodeType::Sequence);
287  for (const auto& element : rhs)
288  node.push_back(element);
289  return node;
290  }
291 
292  static bool decode(const Node& node, std::vector<T, A>& rhs) {
293  if (!node.IsSequence())
294  return false;
295 
296  rhs.clear();
297  for (const auto& element : node)
298 #if defined(__GNUC__) && __GNUC__ < 4
299  // workaround for GCC 3:
300  rhs.push_back(element.template as<T>());
301 #else
302  rhs.push_back(element.as<T>());
303 #endif
304  return true;
305  }
306 };
307 
308 // std::list
309 template <typename T, typename A>
310 struct convert<std::list<T,A>> {
311  static Node encode(const std::list<T,A>& rhs) {
312  Node node(NodeType::Sequence);
313  for (const auto& element : rhs)
314  node.push_back(element);
315  return node;
316  }
317 
318  static bool decode(const Node& node, std::list<T,A>& rhs) {
319  if (!node.IsSequence())
320  return false;
321 
322  rhs.clear();
323  for (const auto& element : node)
324 #if defined(__GNUC__) && __GNUC__ < 4
325  // workaround for GCC 3:
326  rhs.push_back(element.template as<T>());
327 #else
328  rhs.push_back(element.as<T>());
329 #endif
330  return true;
331  }
332 };
333 
334 // std::array
335 template <typename T, std::size_t N>
336 struct convert<std::array<T, N>> {
337  static Node encode(const std::array<T, N>& rhs) {
338  Node node(NodeType::Sequence);
339  for (const auto& element : rhs) {
340  node.push_back(element);
341  }
342  return node;
343  }
344 
345  static bool decode(const Node& node, std::array<T, N>& rhs) {
346  if (!isNodeValid(node)) {
347  return false;
348  }
349 
350  for (auto i = 0u; i < node.size(); ++i) {
351 #if defined(__GNUC__) && __GNUC__ < 4
352  // workaround for GCC 3:
353  rhs[i] = node[i].template as<T>();
354 #else
355  rhs[i] = node[i].as<T>();
356 #endif
357  }
358  return true;
359  }
360 
361  private:
362  static bool isNodeValid(const Node& node) {
363  return node.IsSequence() && node.size() == N;
364  }
365 };
366 
367 
368 // std::valarray
369 template <typename T>
370 struct convert<std::valarray<T>> {
371  static Node encode(const std::valarray<T>& rhs) {
372  Node node(NodeType::Sequence);
373  for (const auto& element : rhs) {
374  node.push_back(element);
375  }
376  return node;
377  }
378 
379  static bool decode(const Node& node, std::valarray<T>& rhs) {
380  if (!node.IsSequence()) {
381  return false;
382  }
383 
384  rhs.resize(node.size());
385  for (auto i = 0u; i < node.size(); ++i) {
386 #if defined(__GNUC__) && __GNUC__ < 4
387  // workaround for GCC 3:
388  rhs[i] = node[i].template as<T>();
389 #else
390  rhs[i] = node[i].as<T>();
391 #endif
392  }
393  return true;
394  }
395 };
396 
397 
398 // std::pair
399 template <typename T, typename U>
400 struct convert<std::pair<T, U>> {
401  static Node encode(const std::pair<T, U>& rhs) {
402  Node node(NodeType::Sequence);
403  node.push_back(rhs.first);
404  node.push_back(rhs.second);
405  return node;
406  }
407 
408  static bool decode(const Node& node, std::pair<T, U>& rhs) {
409  if (!node.IsSequence())
410  return false;
411  if (node.size() != 2)
412  return false;
413 
414 #if defined(__GNUC__) && __GNUC__ < 4
415  // workaround for GCC 3:
416  rhs.first = node[0].template as<T>();
417 #else
418  rhs.first = node[0].as<T>();
419 #endif
420 #if defined(__GNUC__) && __GNUC__ < 4
421  // workaround for GCC 3:
422  rhs.second = node[1].template as<U>();
423 #else
424  rhs.second = node[1].as<U>();
425 #endif
426  return true;
427  }
428 };
429 
430 // binary
431 template <>
432 struct convert<Binary> {
433  static Node encode(const Binary& rhs) {
434  return Node(EncodeBase64(rhs.data(), rhs.size()));
435  }
436 
437  static bool decode(const Node& node, Binary& rhs) {
438  if (!node.IsScalar())
439  return false;
440 
441  std::vector<unsigned char> data = DecodeBase64(node.Scalar());
442  if (data.empty() && !node.Scalar().empty())
443  return false;
444 
445  rhs.swap(data);
446  return true;
447  }
448 };
449 }
450 
451 #endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
Definition: gtest-internal.h:1322
Definition: anchor.h:12