1 #ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 2 #define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 4 #if defined(_MSC_VER) || \ 5 (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ 6 (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 15 #include <unordered_map> 17 #include <type_traits> 21 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) 22 #include <string_view> 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" 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";
48 inline bool IsNegativeInfinity(
const std::string& input) {
49 return input ==
"-.inf" || input ==
"-.Inf" || input ==
"-.INF";
52 inline bool IsNaN(
const std::string& input) {
53 return input ==
".nan" || input ==
".NaN" || input ==
".NAN";
60 static Node encode(
const Node& rhs) {
return rhs; }
62 static bool decode(
const Node& node,
Node& rhs) {
71 static Node encode(
const std::string& rhs) {
return Node(rhs); }
73 static bool decode(
const Node& node, std::string& rhs) {
84 static Node encode(
const char* rhs) {
return Node(rhs); }
89 static Node encode(
const char* rhs) {
return Node(rhs); }
92 template <std::
size_t N>
94 static Node encode(
const char* rhs) {
return Node(rhs); }
97 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) 99 struct convert<std::string_view> {
100 static Node encode(std::string_view rhs) {
return Node(std::string(rhs)); }
102 static bool decode(
const Node& node, std::string_view& rhs) {
103 if (!node.IsScalar())
115 static bool decode(
const Node& node,
_Null& ) {
116 return node.IsNull();
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)) {
126 }
else if (std::isinf(rhs)) {
127 if (std::signbit(rhs)) {
133 stream << FpToString(rhs, stream.precision());
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){
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) {
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);
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()) {
169 #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ 171 struct convert<type> { \ 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()); \ 181 static bool decode(const Node& node, type& rhs) { \ 182 if (node.Type() != NodeType::Scalar) { \ 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) { \ 192 if (conversion::ConvertStreamTo(stream, rhs)) { \ 195 if (std::numeric_limits<type>::has_infinity) { \ 196 if (conversion::IsInfinity(input)) { \ 197 rhs = std::numeric_limits<type>::infinity(); \ 199 } else if (conversion::IsNegativeInfinity(input)) { \ 200 rhs = negative_op std::numeric_limits<type>::infinity(); \ 205 if (std::numeric_limits<type>::has_quiet_NaN) { \ 206 if (conversion::IsNaN(input)) { \ 207 rhs = std::numeric_limits<type>::quiet_NaN(); \ 216 #define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \ 217 YAML_DEFINE_CONVERT_STREAMABLE(type, -) 219 #define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \ 220 YAML_DEFINE_CONVERT_STREAMABLE(type, +) 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);
231 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(
char);
232 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(
signed char);
233 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(
unsigned char);
235 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(
float);
236 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(
double);
237 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(
long double);
239 #undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED 240 #undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED 241 #undef YAML_DEFINE_CONVERT_STREAMABLE 246 static Node encode(
bool rhs) {
return rhs ?
Node(
"true") : Node(
"false"); }
248 YAML_CPP_API
static bool decode(
const Node& node,
bool& rhs);
252 template <
typename K,
typename V,
typename C,
typename 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);
261 static bool decode(
const Node& node, std::map<K, V, C, A>& rhs) {
266 for (
const auto& element : node)
267 #if defined(__GNUC__) && __GNUC__ < 4 269 rhs[element.first.template as<K>()] = element.second.template as<V>();
271 rhs[element.first.as<K>()] = element.second.as<V>();
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);
287 static bool decode(
const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
292 for (
const auto& element : node)
293 #if defined(__GNUC__) && __GNUC__ < 4 295 rhs[element.first.template as<K>()] = element.second.template as<V>();
297 rhs[element.first.as<K>()] = element.second.as<V>();
304 template <
typename T,
typename 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);
313 static bool decode(
const Node& node, std::vector<T, A>& rhs) {
314 if (!node.IsSequence())
318 for (
const auto& element : node)
319 #if defined(__GNUC__) && __GNUC__ < 4 321 rhs.push_back(element.template as<T>());
323 rhs.push_back(element.as<T>());
330 template <
typename T,
typename 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);
339 static bool decode(
const Node& node, std::list<T,A>& rhs) {
340 if (!node.IsSequence())
344 for (
const auto& element : node)
345 #if defined(__GNUC__) && __GNUC__ < 4 347 rhs.push_back(element.template as<T>());
349 rhs.push_back(element.as<T>());
356 template <
typename T, std::
size_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);
366 static bool decode(
const Node& node, std::array<T, N>& rhs) {
367 if (!isNodeValid(node)) {
371 for (
auto i = 0u; i < node.size(); ++i) {
372 #if defined(__GNUC__) && __GNUC__ < 4 374 rhs[i] = node[i].template as<T>();
376 rhs[i] = node[i].as<T>();
383 static bool isNodeValid(
const Node& node) {
384 return node.IsSequence() && node.size() == N;
390 template <
typename 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);
400 static bool decode(
const Node& node, std::valarray<T>& rhs) {
401 if (!node.IsSequence()) {
405 rhs.resize(node.size());
406 for (
auto i = 0u; i < node.size(); ++i) {
407 #if defined(__GNUC__) && __GNUC__ < 4 409 rhs[i] = node[i].template as<T>();
411 rhs[i] = node[i].as<T>();
420 template <
typename T,
typename 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);
429 static bool decode(
const Node& node, std::pair<T, U>& rhs) {
430 if (!node.IsSequence())
432 if (node.size() != 2)
435 #if defined(__GNUC__) && __GNUC__ < 4 437 rhs.first = node[0].template as<T>();
439 rhs.first = node[0].as<T>();
441 #if defined(__GNUC__) && __GNUC__ < 4 443 rhs.second = node[1].template as<U>();
445 rhs.second = node[1].as<U>();
455 return Node(EncodeBase64(rhs.data(), rhs.size()));
458 static bool decode(
const Node& node,
Binary& rhs) {
459 if (!node.IsScalar())
462 std::vector<unsigned char> data = DecodeBase64(node.Scalar());
463 if (data.empty() && !node.Scalar().empty())
472 #endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66