json_value.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright (c) 2018-2020 Jsonxx - Nomango
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #pragma once
  21. #include <memory> // std::allocator_traits
  22. #include "json_exception.hpp"
  23. namespace jsonxx {
  24. //
  25. // json value type
  26. //
  27. enum class json_type {
  28. number_integer,
  29. number_float,
  30. string,
  31. array,
  32. object,
  33. boolean,
  34. null,
  35. };
  36. //
  37. // json_value
  38. //
  39. template<typename _BasicJsonTy>
  40. struct json_value {
  41. using string_type = typename _BasicJsonTy::string_type;
  42. using char_type = typename _BasicJsonTy::char_type;
  43. using integer_type = typename _BasicJsonTy::integer_type;
  44. using float_type = typename _BasicJsonTy::float_type;
  45. using boolean_type = typename _BasicJsonTy::boolean_type;
  46. using array_type = typename _BasicJsonTy::array_type;
  47. using object_type = typename _BasicJsonTy::object_type;
  48. json_type type;
  49. union {
  50. object_type *object;
  51. array_type *vector;
  52. string_type *string;
  53. integer_type number_integer;
  54. float_type number_float;
  55. boolean_type boolean;
  56. } data;
  57. json_value() {
  58. type = json_type::null;
  59. data.object = nullptr;
  60. }
  61. json_value(std::nullptr_t) {
  62. type = json_type::null;
  63. data.object = nullptr;
  64. }
  65. json_value(const object_type &value) {
  66. type = json_type::object;
  67. data.object = create<object_type>(value);
  68. }
  69. json_value(const array_type &value) {
  70. type = json_type::array;
  71. data.vector = create<array_type>(value);
  72. }
  73. json_value(const string_type &value) {
  74. type = json_type::string;
  75. data.string = create<string_type>(value);
  76. }
  77. template<typename _CharT>
  78. json_value(const _CharT *str) {
  79. type = json_type::string;
  80. data.string = create<string_type>(str);
  81. }
  82. json_value(const integer_type value) {
  83. type = json_type::number_integer;
  84. data.number_integer = value;
  85. }
  86. json_value(const float_type value) {
  87. type = json_type::number_float;
  88. data.number_float = value;
  89. }
  90. json_value(const boolean_type value) {
  91. type = json_type::boolean;
  92. data.boolean = value;
  93. }
  94. json_value(const json_type value_type) {
  95. type = value_type;
  96. switch (type) {
  97. case json_type::object:
  98. data.object = create<object_type>();
  99. break;
  100. case json_type::array:
  101. data.vector = create<array_type>();
  102. break;
  103. case json_type::string:
  104. data.string = create<string_type>();
  105. break;
  106. case json_type::number_integer:
  107. data.number_integer = integer_type(0);
  108. break;
  109. case json_type::number_float:
  110. data.number_float = float_type(0.0);
  111. break;
  112. case json_type::boolean:
  113. data.boolean = boolean_type(false);
  114. break;
  115. default:
  116. data.object = nullptr;
  117. break;
  118. }
  119. }
  120. json_value(json_value const &other) {
  121. type = other.type;
  122. switch (other.type) {
  123. case json_type::object:
  124. data.object = create<object_type>(*other.data.object);
  125. break;
  126. case json_type::array:
  127. data.vector = create<array_type>(*other.data.vector);
  128. break;
  129. case json_type::string:
  130. data.string = create<string_type>(*other.data.string);
  131. break;
  132. case json_type::number_integer:
  133. data.number_integer = other.data.number_integer;
  134. break;
  135. case json_type::number_float:
  136. data.number_float = other.data.number_float;
  137. break;
  138. case json_type::boolean:
  139. data.boolean = other.data.boolean;
  140. break;
  141. default:
  142. data.object = nullptr;
  143. break;
  144. }
  145. }
  146. json_value(json_value &&other) {
  147. type = other.type;
  148. data = other.data;
  149. other.type = json_type::null;
  150. other.data.object = nullptr;
  151. }
  152. ~json_value() {
  153. clear();
  154. }
  155. void swap(json_value &other) {
  156. std::swap(type, other.type);
  157. std::swap(data, other.data);
  158. }
  159. void clear() {
  160. switch (type) {
  161. case json_type::object:
  162. destroy<object_type>(data.object);
  163. break;
  164. case json_type::array:
  165. destroy<array_type>(data.vector);
  166. break;
  167. case json_type::string:
  168. destroy<string_type>(data.string);
  169. break;
  170. default:
  171. break;
  172. }
  173. }
  174. template<typename _Ty, typename... _Args>
  175. inline _Ty *create(_Args &&... args) {
  176. using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>;
  177. using allocator_traits = std::allocator_traits<allocator_type>;
  178. allocator_type allocator;
  179. _Ty *ptr = allocator_traits::allocate(allocator, 1);
  180. allocator_traits::construct(allocator, ptr, std::forward<_Args>(args)...);
  181. return ptr;
  182. }
  183. template<typename _Ty>
  184. inline void destroy(_Ty *ptr) {
  185. using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>;
  186. using allocator_traits = std::allocator_traits<allocator_type>;
  187. allocator_type allocator;
  188. allocator_traits::destroy(allocator, ptr);
  189. allocator_traits::deallocate(allocator, ptr, 1);
  190. }
  191. inline json_value &operator=(json_value const &other) {
  192. json_value{other}.swap(*this);
  193. return (*this);
  194. }
  195. inline json_value &operator=(json_value &&other) {
  196. clear();
  197. type = other.type;
  198. data = std::move(other.data);
  199. // invalidate payload
  200. other.type = json_type::null;
  201. other.data.object = nullptr;
  202. return (*this);
  203. }
  204. };
  205. //
  206. // json_value_getter
  207. //
  208. template<typename _BasicJsonTy>
  209. struct json_value_getter {
  210. using string_type = typename _BasicJsonTy::string_type;
  211. using char_type = typename _BasicJsonTy::char_type;
  212. using integer_type = typename _BasicJsonTy::integer_type;
  213. using float_type = typename _BasicJsonTy::float_type;
  214. using boolean_type = typename _BasicJsonTy::boolean_type;
  215. using array_type = typename _BasicJsonTy::array_type;
  216. using object_type = typename _BasicJsonTy::object_type;
  217. static inline void assign(const _BasicJsonTy &json, object_type &value) {
  218. if (!json.is_object())
  219. throw json_type_error("json value type must be object");
  220. value = *json.value_.data.object;
  221. }
  222. static inline void assign(const _BasicJsonTy &json, array_type &value) {
  223. if (!json.is_array())
  224. throw json_type_error("json value type must be array");
  225. value = *json.value_.data.vector;
  226. }
  227. static inline void assign(const _BasicJsonTy &json, string_type &value) {
  228. if (!json.is_string())
  229. throw json_type_error("json value type must be string");
  230. value = *json.value_.data.string;
  231. }
  232. static inline void assign(const _BasicJsonTy &json, boolean_type &value) {
  233. if (!json.is_boolean())
  234. throw json_type_error("json value type must be boolean");
  235. value = json.value_.data.boolean;
  236. }
  237. static inline void assign(const _BasicJsonTy &json, integer_type &value) {
  238. if (!json.is_integer())
  239. throw json_type_error("json value type must be integer");
  240. value = json.value_.data.number_integer;
  241. }
  242. template<
  243. typename _IntegerTy,
  244. typename std::enable_if<std::is_integral<_IntegerTy>::value, int>::type = 0>
  245. static inline void assign(const _BasicJsonTy &json, _IntegerTy &value) {
  246. if (!json.is_integer())
  247. throw json_type_error("json value type must be integer");
  248. value = static_cast<_IntegerTy>(json.value_.data.number_integer);
  249. }
  250. static inline void assign(const _BasicJsonTy &json, float_type &value) {
  251. if (!json.is_float())
  252. throw json_type_error("json value type must be float");
  253. value = json.value_.data.number_float;
  254. }
  255. template<
  256. typename _FloatingTy,
  257. typename std::enable_if<std::is_floating_point<_FloatingTy>::value, int>::type = 0>
  258. static inline void assign(const _BasicJsonTy &json, _FloatingTy &value) {
  259. if (!json.is_float())
  260. throw json_type_error("json value type must be float");
  261. value = static_cast<_FloatingTy>(json.value_.data.number_float);
  262. }
  263. };
  264. } // namespace Jsonxx