Back to home page

EIC code displayed by LXR

 
 

    


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))  // GCC supports "pragma once" correctly since 3.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 }  // namespace YAML
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 // Node
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 // std::string
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 // C-strings can only be encoded
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& /* rhs */) { return Node(); }
0093 
0094   static bool decode(const Node& node, _Null& /* rhs */) {
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 // bool
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 // std::map
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       // workaround for GCC 3:
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 // std::vector
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       // workaround for GCC 3:
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 // std::list
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       // workaround for GCC 3:
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 // std::array
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       // workaround for GCC 3:
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 // std::pair
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     // workaround for GCC 3:
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     // workaround for GCC 3:
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 // binary
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  // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66