LCOV - code coverage report
Current view: top level - usr/include/yaml-cpp/node - convert.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 19 40 47.5 %
Date: 2025-08-24 09:11:10 Functions: 13 29 44.8 %

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

Generated by: LCOV version 1.14