Coverage Report

Created: 2026-02-10 06:42

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