json_binder.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // json_binder.h
  3. // json
  4. //
  5. // Created by Sam Jaffe on 1/31/16.
  6. // Copyright © 2016 Sam Jaffe. All rights reserved.
  7. //
  8. #ifndef json_binder_h
  9. #define json_binder_h
  10. #pragma once
  11. namespace json {
  12. namespace binder {
  13. template <typename T>
  14. class binder_impl {
  15. public:
  16. virtual binder_impl<T>* clone() const = 0;
  17. virtual ~binder_impl() {}
  18. virtual void parse(T&, char const*&) const = 0;
  19. };
  20. template <typename T>
  21. class binder {
  22. public:
  23. binder() : impl(nullptr), owned(false) {}
  24. binder(binder const& other) : impl(other.impl->clone()), owned(true) {}
  25. binder(binder_impl<T> const* p) : impl(p), owned(true) {}
  26. binder(binder_impl<T> const& r) : impl(&r), owned(false) {}
  27. ~binder() { if (impl && owned) delete impl; }
  28. void parse(T& object, char const*& data) const {
  29. if (!impl) return;
  30. impl->parse(object, data);
  31. }
  32. private:
  33. binder_impl<T> const* impl;
  34. bool owned;
  35. };
  36. template <typename T, typename E>
  37. class direct_binder : public binder_impl<T> {
  38. public:
  39. direct_binder(E T::*p, binder<E> const& i) : ptr(p), impl(i) {}
  40. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  41. virtual void parse(T& val, char const*& data) const override {
  42. impl.parse(val.*ptr, data);
  43. }
  44. private:
  45. E T::*ptr;
  46. binder<E> impl;
  47. };
  48. template <typename T>
  49. class direct_binder<T, bool> : public binder_impl<T> {
  50. public:
  51. direct_binder(bool T::*p) : ptr(p) {}
  52. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  53. virtual void parse(T& val, char const*& data) override {
  54. if (!strncmp(data, "true", 4)) {
  55. val.*ptr = true;
  56. } else if (!strncmp(data, "false", 5)) {
  57. val.*ptr = false;
  58. } else {
  59. throw json::malformed_json_exception("Expected a boolean type here");
  60. }
  61. }
  62. private:
  63. bool T::*ptr;
  64. };
  65. template <typename T>
  66. class direct_binder<T, int> : public binder_impl<T> {
  67. public:
  68. direct_binder(int T::*p) : ptr(p) {}
  69. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  70. virtual void parse(T& val, char const*& data) const override {
  71. // if (false) {
  72. json::helper::parse_numeric(val.*ptr, data);
  73. // } else {
  74. // throw json::malformed_json_exception("Expected an integral type here");
  75. // }
  76. }
  77. private:
  78. int T::*ptr;
  79. };
  80. template <typename T>
  81. class direct_binder<T, double> : public binder_impl<T> {
  82. public:
  83. direct_binder(double T::*p) : ptr(p) {}
  84. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  85. virtual void parse(T& val, char const*& data) const override {
  86. // if (false) {
  87. json::helper::parse_numeric(val.*ptr, data);
  88. // } else {
  89. // throw json::malformed_json_exception("Expected a floating point type here");
  90. // }
  91. }
  92. private:
  93. double T::*ptr;
  94. };
  95. template <typename T>
  96. class direct_binder<T, std::string> : public binder_impl<T> {
  97. public:
  98. direct_binder(std::string T::*p) : ptr(p) {}
  99. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  100. virtual void parse(T& val, char const*& data) const override {
  101. json::helper::parse_string(val.*ptr, data);
  102. }
  103. private:
  104. std::string T::*ptr;
  105. };
  106. template <typename T, typename V>
  107. class direct_binder<T, std::vector<V> > : public binder_impl<T> {
  108. public:
  109. direct_binder(std::vector<V> T::*p, binder<V> const&i);
  110. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  111. virtual void parse(T& val, char const*& data) const override {
  112. const char ch = json::helper::get_next_element(data);
  113. if (ch != '[') {
  114. throw json::malformed_json_exception("Expected an array type");
  115. }
  116. ++data;
  117. V to_make;
  118. std::vector<V>& vec = val.*ptr;
  119. while (*data && *data != ']') {
  120. impl.parse(to_make, data);
  121. vec.emplace_back(to_make);
  122. json::helper::advance_to_boundary<']'>(data);
  123. }
  124. if (*data) ++data;
  125. else throw json::malformed_json_exception("Reached end of parse string without finding array end");
  126. }
  127. private:
  128. std::vector<V> T::*ptr;
  129. binder<V> impl;
  130. };
  131. template <typename T, typename V>
  132. class direct_binder<T, std::map<std::string, V> > : public binder_impl<T> {
  133. public:
  134. direct_binder(std::vector<V> T::*p, binder<V> const&i);
  135. virtual binder_impl<T>* clone() const override { return new direct_binder(*this); }
  136. virtual void parse(T& val, char const*& data) const override {
  137. const char ch = json::helper::get_next_element(data);
  138. if (ch != '{') {
  139. throw json::malformed_json_exception("Expected an array type");
  140. }
  141. ++data;
  142. V to_make;
  143. std::map<std::string, V>& vec = val.*ptr;
  144. std::string key;
  145. while (*data && *data != '}') {
  146. json::helper::parse_string(key, data);
  147. if (json::helper::get_next_element(data) != ':') {
  148. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  149. }
  150. impl.parse(to_make, ++data);
  151. vec.emplace(key, to_make);
  152. json::helper::advance_to_boundary<'}'>(data);
  153. }
  154. if (*data) ++data;
  155. else throw json::malformed_json_exception("Reached end of parse string without finding object end");
  156. }
  157. private:
  158. std::map<std::string, V> T::*ptr;
  159. binder<V> impl;
  160. };
  161. template <typename T>
  162. class object_binder : public binder_impl<T> {
  163. public:
  164. object_binder() {}
  165. virtual binder_impl<T>* clone() const override { return new object_binder(*this); }
  166. template <typename V>
  167. object_binder& operator()(std::string const&k, V T::*ptr, binder_impl<V> const&v) {
  168. return (*this)(k, binder<T>(new direct_binder<T, V>(ptr, binder<V>(v) )));
  169. }
  170. object_binder& operator()(std::string const&k, binder<T> const&v) {
  171. mapping.emplace(k, v);
  172. return *this;
  173. }
  174. virtual void parse(T& object, char const*& data) const override {
  175. const char ch = json::helper::get_next_element(data);
  176. if (ch == '{') {
  177. parse_object(object, ++data);
  178. } else {
  179. throw json::malformed_json_exception(std::string("Expected an object type for binding to ") + typeid(T).name());
  180. }
  181. }
  182. void parse_object(T& object, char const*& data) const {
  183. std::string key;
  184. while (*data && *data != '}') {
  185. json::helper::parse_string(key, data);
  186. if (json::helper::get_next_element(data) != ':') {
  187. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  188. }
  189. auto it = mapping.find(key);
  190. if (it != mapping.end()) {
  191. it->second.parse(object, ++data);
  192. } else {
  193. throw json::malformed_json_exception("Unexpected key " + key);
  194. }
  195. json::helper::advance_to_boundary<'}'>(data);
  196. }
  197. if (*data) ++data;
  198. else throw json::malformed_json_exception("Reached end of parse string without finding object end");
  199. }
  200. template <typename E>
  201. object_binder& operator()(std::string const& s, E T::*p) {
  202. return operator()(s, binder<T>(new direct_binder<T, E>(p)));
  203. }
  204. private:
  205. std::map<std::string, binder<T>> mapping;
  206. };
  207. template <typename T>
  208. class tuple_binder : public binder_impl<T> {
  209. public:
  210. virtual binder_impl<T>* clone() const override { return new tuple_binder(*this); }
  211. tuple_binder& operator()(binder<T> const&b) {
  212. members.push_back(b);
  213. return *this;
  214. }
  215. virtual void parse(T& object, char const*& data) const override {
  216. const char ch = json::helper::get_next_element(data);
  217. if (ch == '[') {
  218. parse_tuple(object, ++data);
  219. } else {
  220. throw json::malformed_json_exception(std::string("Expected an object type for binding to ") + typeid(T).name());
  221. }
  222. }
  223. void parse_tuple(T& object, char const*& data) const {
  224. auto it = members.begin();
  225. while (*data && *data != ']' && it != members.end()) {
  226. it->parse(object, data);
  227. json::helper::advance_to_boundary<']'>(data);
  228. ++it;
  229. }
  230. if (it != members.end()) {
  231. throw json::malformed_json_exception("Failed to parse every member of tuple");
  232. }
  233. if (*data) ++data;
  234. else throw json::malformed_json_exception("Reached end of parse string without finding array end");
  235. }
  236. template <typename E>
  237. tuple_binder& operator()(E T::*p) {
  238. return operator()(binder<T>(new direct_binder<T, E>(p)));
  239. }
  240. private:
  241. std::vector<binder<T>> members;
  242. };
  243. template <typename T>
  244. class visitor {
  245. public:
  246. visitor(T& o, binder_impl<T>& b) : obj(o), b(b) {}
  247. void parse(char const* data) {
  248. b.parse(obj, data);
  249. }
  250. private:
  251. T& obj;
  252. binder_impl<T>& b;
  253. };
  254. template <typename T>
  255. visitor<T> bind(T& object, binder_impl<T>& b) {
  256. return visitor<T>{object, b};
  257. }
  258. }
  259. namespace parser {
  260. template <typename T>
  261. void parse(binder::visitor<T>& visitor, char const* data) {
  262. visitor.parse(data);
  263. }
  264. }
  265. }
  266. #endif /* json_binder_h */