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