File indexing completed on 2025-06-30 08:55:05
0001 #ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
0002 #define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
0003
0004 #if defined(_MSC_VER) || \
0005 (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
0006 (__GNUC__ >= 4))
0007 #pragma once
0008 #endif
0009
0010 #include <array>
0011 #include <cmath>
0012 #include <limits>
0013 #include <list>
0014 #include <map>
0015 #include <unordered_map>
0016 #include <sstream>
0017 #include <type_traits>
0018 #include <valarray>
0019 #include <vector>
0020
0021 #if __cplusplus >= 201703L
0022 #include <string_view>
0023 #endif
0024
0025 #include "yaml-cpp/binary.h"
0026 #include "yaml-cpp/node/impl.h"
0027 #include "yaml-cpp/node/iterator.h"
0028 #include "yaml-cpp/node/node.h"
0029 #include "yaml-cpp/node/type.h"
0030 #include "yaml-cpp/null.h"
0031
0032
0033 namespace YAML {
0034 class Binary;
0035 struct _Null;
0036 template <typename T>
0037 struct convert;
0038 }
0039
0040 namespace YAML {
0041 namespace conversion {
0042 inline bool IsInfinity(const std::string& input) {
0043 return input == ".inf" || input == ".Inf" || input == ".INF" ||
0044 input == "+.inf" || input == "+.Inf" || input == "+.INF";
0045 }
0046
0047 inline bool IsNegativeInfinity(const std::string& input) {
0048 return input == "-.inf" || input == "-.Inf" || input == "-.INF";
0049 }
0050
0051 inline bool IsNaN(const std::string& input) {
0052 return input == ".nan" || input == ".NaN" || input == ".NAN";
0053 }
0054 }
0055
0056
0057 template <>
0058 struct convert<Node> {
0059 static Node encode(const Node& rhs) { return rhs; }
0060
0061 static bool decode(const Node& node, Node& rhs) {
0062 rhs.reset(node);
0063 return true;
0064 }
0065 };
0066
0067
0068 template <>
0069 struct convert<std::string> {
0070 static Node encode(const std::string& rhs) { return Node(rhs); }
0071
0072 static bool decode(const Node& node, std::string& rhs) {
0073 if (!node.IsScalar())
0074 return false;
0075 rhs = node.Scalar();
0076 return true;
0077 }
0078 };
0079
0080
0081 template <>
0082 struct convert<const char*> {
0083 static Node encode(const char* rhs) { return Node(rhs); }
0084 };
0085
0086 template <>
0087 struct convert<char*> {
0088 static Node encode(const char* rhs) { return Node(rhs); }
0089 };
0090
0091 template <std::size_t N>
0092 struct convert<char[N]> {
0093 static Node encode(const char* rhs) { return Node(rhs); }
0094 };
0095
0096 #if __cplusplus >= 201703L
0097 template <>
0098 struct convert<std::string_view> {
0099 static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
0100
0101 static bool decode(const Node& node, std::string_view& rhs) {
0102 if (!node.IsScalar())
0103 return false;
0104 rhs = node.Scalar();
0105 return true;
0106 }
0107 };
0108 #endif
0109
0110 template <>
0111 struct convert<_Null> {
0112 static Node encode(const _Null& ) { return Node(); }
0113
0114 static bool decode(const Node& node, _Null& ) {
0115 return node.IsNull();
0116 }
0117 };
0118
0119 namespace conversion {
0120 template <typename T>
0121 typename std::enable_if< std::is_floating_point<T>::value, void>::type
0122 inner_encode(const T& rhs, std::stringstream& stream){
0123 if (std::isnan(rhs)) {
0124 stream << ".nan";
0125 } else if (std::isinf(rhs)) {
0126 if (std::signbit(rhs)) {
0127 stream << "-.inf";
0128 } else {
0129 stream << ".inf";
0130 }
0131 } else {
0132 stream << rhs;
0133 }
0134 }
0135
0136 template <typename T>
0137 typename std::enable_if<!std::is_floating_point<T>::value, void>::type
0138 inner_encode(const T& rhs, std::stringstream& stream){
0139 stream << rhs;
0140 }
0141
0142 template <typename T>
0143 typename std::enable_if<(std::is_same<T, unsigned char>::value ||
0144 std::is_same<T, signed char>::value), bool>::type
0145 ConvertStreamTo(std::stringstream& stream, T& rhs) {
0146 int num;
0147 if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
0148 if (num >= (std::numeric_limits<T>::min)() &&
0149 num <= (std::numeric_limits<T>::max)()) {
0150 rhs = static_cast<T>(num);
0151 return true;
0152 }
0153 }
0154 return false;
0155 }
0156
0157 template <typename T>
0158 typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
0159 std::is_same<T, signed char>::value), bool>::type
0160 ConvertStreamTo(std::stringstream& stream, T& rhs) {
0161 if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
0162 return true;
0163 }
0164 return false;
0165 }
0166 }
0167
0168 #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
0169 template <> \
0170 struct convert<type> { \
0171 \
0172 static Node encode(const type& rhs) { \
0173 std::stringstream stream; \
0174 stream.precision(std::numeric_limits<type>::max_digits10); \
0175 conversion::inner_encode(rhs, stream); \
0176 return Node(stream.str()); \
0177 } \
0178 \
0179 static bool decode(const Node& node, type& rhs) { \
0180 if (node.Type() != NodeType::Scalar) { \
0181 return false; \
0182 } \
0183 const std::string& input = node.Scalar(); \
0184 std::stringstream stream(input); \
0185 stream.unsetf(std::ios::dec); \
0186 if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
0187 return false; \
0188 } \
0189 if (conversion::ConvertStreamTo(stream, rhs)) { \
0190 return true; \
0191 } \
0192 if (std::numeric_limits<type>::has_infinity) { \
0193 if (conversion::IsInfinity(input)) { \
0194 rhs = std::numeric_limits<type>::infinity(); \
0195 return true; \
0196 } else if (conversion::IsNegativeInfinity(input)) { \
0197 rhs = negative_op std::numeric_limits<type>::infinity(); \
0198 return true; \
0199 } \
0200 } \
0201 \
0202 if (std::numeric_limits<type>::has_quiet_NaN) { \
0203 if (conversion::IsNaN(input)) { \
0204 rhs = std::numeric_limits<type>::quiet_NaN(); \
0205 return true; \
0206 } \
0207 } \
0208 \
0209 return false; \
0210 } \
0211 }
0212
0213 #define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
0214 YAML_DEFINE_CONVERT_STREAMABLE(type, -)
0215
0216 #define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
0217 YAML_DEFINE_CONVERT_STREAMABLE(type, +)
0218
0219 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
0220 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
0221 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
0222 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
0223 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
0224 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
0225 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
0226 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
0227
0228 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
0229 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
0230 YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
0231
0232 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
0233 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
0234 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
0235
0236 #undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
0237 #undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
0238 #undef YAML_DEFINE_CONVERT_STREAMABLE
0239
0240
0241 template <>
0242 struct convert<bool> {
0243 static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
0244
0245 YAML_CPP_API static bool decode(const Node& node, bool& rhs);
0246 };
0247
0248
0249 template <typename K, typename V, typename C, typename A>
0250 struct convert<std::map<K, V, C, A>> {
0251 static Node encode(const std::map<K, V, C, A>& rhs) {
0252 Node node(NodeType::Map);
0253 for (const auto& element : rhs)
0254 node.force_insert(element.first, element.second);
0255 return node;
0256 }
0257
0258 static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
0259 if (!node.IsMap())
0260 return false;
0261
0262 rhs.clear();
0263 for (const auto& element : node)
0264 #if defined(__GNUC__) && __GNUC__ < 4
0265
0266 rhs[element.first.template as<K>()] = element.second.template as<V>();
0267 #else
0268 rhs[element.first.as<K>()] = element.second.as<V>();
0269 #endif
0270 return true;
0271 }
0272 };
0273
0274
0275 template <typename K, typename V, typename H, typename P, typename A>
0276 struct convert<std::unordered_map<K, V, H, P, A>> {
0277 static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
0278 Node node(NodeType::Map);
0279 for (const auto& element : rhs)
0280 node.force_insert(element.first, element.second);
0281 return node;
0282 }
0283
0284 static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
0285 if (!node.IsMap())
0286 return false;
0287
0288 rhs.clear();
0289 for (const auto& element : node)
0290 #if defined(__GNUC__) && __GNUC__ < 4
0291
0292 rhs[element.first.template as<K>()] = element.second.template as<V>();
0293 #else
0294 rhs[element.first.as<K>()] = element.second.as<V>();
0295 #endif
0296 return true;
0297 }
0298 };
0299
0300
0301 template <typename T, typename A>
0302 struct convert<std::vector<T, A>> {
0303 static Node encode(const std::vector<T, A>& rhs) {
0304 Node node(NodeType::Sequence);
0305 for (const auto& element : rhs)
0306 node.push_back(element);
0307 return node;
0308 }
0309
0310 static bool decode(const Node& node, std::vector<T, A>& rhs) {
0311 if (!node.IsSequence())
0312 return false;
0313
0314 rhs.clear();
0315 for (const auto& element : node)
0316 #if defined(__GNUC__) && __GNUC__ < 4
0317
0318 rhs.push_back(element.template as<T>());
0319 #else
0320 rhs.push_back(element.as<T>());
0321 #endif
0322 return true;
0323 }
0324 };
0325
0326
0327 template <typename T, typename A>
0328 struct convert<std::list<T,A>> {
0329 static Node encode(const std::list<T,A>& rhs) {
0330 Node node(NodeType::Sequence);
0331 for (const auto& element : rhs)
0332 node.push_back(element);
0333 return node;
0334 }
0335
0336 static bool decode(const Node& node, std::list<T,A>& rhs) {
0337 if (!node.IsSequence())
0338 return false;
0339
0340 rhs.clear();
0341 for (const auto& element : node)
0342 #if defined(__GNUC__) && __GNUC__ < 4
0343
0344 rhs.push_back(element.template as<T>());
0345 #else
0346 rhs.push_back(element.as<T>());
0347 #endif
0348 return true;
0349 }
0350 };
0351
0352
0353 template <typename T, std::size_t N>
0354 struct convert<std::array<T, N>> {
0355 static Node encode(const std::array<T, N>& rhs) {
0356 Node node(NodeType::Sequence);
0357 for (const auto& element : rhs) {
0358 node.push_back(element);
0359 }
0360 return node;
0361 }
0362
0363 static bool decode(const Node& node, std::array<T, N>& rhs) {
0364 if (!isNodeValid(node)) {
0365 return false;
0366 }
0367
0368 for (auto i = 0u; i < node.size(); ++i) {
0369 #if defined(__GNUC__) && __GNUC__ < 4
0370
0371 rhs[i] = node[i].template as<T>();
0372 #else
0373 rhs[i] = node[i].as<T>();
0374 #endif
0375 }
0376 return true;
0377 }
0378
0379 private:
0380 static bool isNodeValid(const Node& node) {
0381 return node.IsSequence() && node.size() == N;
0382 }
0383 };
0384
0385
0386
0387 template <typename T>
0388 struct convert<std::valarray<T>> {
0389 static Node encode(const std::valarray<T>& rhs) {
0390 Node node(NodeType::Sequence);
0391 for (const auto& element : rhs) {
0392 node.push_back(element);
0393 }
0394 return node;
0395 }
0396
0397 static bool decode(const Node& node, std::valarray<T>& rhs) {
0398 if (!node.IsSequence()) {
0399 return false;
0400 }
0401
0402 rhs.resize(node.size());
0403 for (auto i = 0u; i < node.size(); ++i) {
0404 #if defined(__GNUC__) && __GNUC__ < 4
0405
0406 rhs[i] = node[i].template as<T>();
0407 #else
0408 rhs[i] = node[i].as<T>();
0409 #endif
0410 }
0411 return true;
0412 }
0413 };
0414
0415
0416
0417 template <typename T, typename U>
0418 struct convert<std::pair<T, U>> {
0419 static Node encode(const std::pair<T, U>& rhs) {
0420 Node node(NodeType::Sequence);
0421 node.push_back(rhs.first);
0422 node.push_back(rhs.second);
0423 return node;
0424 }
0425
0426 static bool decode(const Node& node, std::pair<T, U>& rhs) {
0427 if (!node.IsSequence())
0428 return false;
0429 if (node.size() != 2)
0430 return false;
0431
0432 #if defined(__GNUC__) && __GNUC__ < 4
0433
0434 rhs.first = node[0].template as<T>();
0435 #else
0436 rhs.first = node[0].as<T>();
0437 #endif
0438 #if defined(__GNUC__) && __GNUC__ < 4
0439
0440 rhs.second = node[1].template as<U>();
0441 #else
0442 rhs.second = node[1].as<U>();
0443 #endif
0444 return true;
0445 }
0446 };
0447
0448
0449 template <>
0450 struct convert<Binary> {
0451 static Node encode(const Binary& rhs) {
0452 return Node(EncodeBase64(rhs.data(), rhs.size()));
0453 }
0454
0455 static bool decode(const Node& node, Binary& rhs) {
0456 if (!node.IsScalar())
0457 return false;
0458
0459 std::vector<unsigned char> data = DecodeBase64(node.Scalar());
0460 if (data.empty() && !node.Scalar().empty())
0461 return false;
0462
0463 rhs.swap(data);
0464 return true;
0465 }
0466 };
0467 }
0468
0469 #endif