convert.h 12 KB

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