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