jsoncons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. metadata +268 -0
@@ -0,0 +1,1830 @@
1
+ // Copyright 2013 Daniel Parker
2
+ // Distributed under the Boost license, Version 1.0.
3
+ // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ // See https://github.com/danielaparker/jsoncons for latest version
6
+
7
+ #ifndef JSONCONS_JSON_TYPE_TRAITS_HPP
8
+ #define JSONCONS_JSON_TYPE_TRAITS_HPP
9
+
10
+ #include <chrono>
11
+ #include <array>
12
+ #include <string>
13
+ #include <vector>
14
+ #include <valarray>
15
+ #include <exception>
16
+ #include <cstring>
17
+ #include <utility>
18
+ #include <algorithm> // std::swap
19
+ #include <limits> // std::numeric_limits
20
+ #include <type_traits> // std::enable_if
21
+ #include <iterator> // std::iterator_traits, std::input_iterator_tag
22
+ #include <jsoncons/json_type.hpp>
23
+ #include <jsoncons/bigint.hpp>
24
+ #include <jsoncons/json_visitor.hpp>
25
+ #include <jsoncons/traits_extension.hpp>
26
+ #include <string>
27
+ #include <tuple>
28
+ #include <map>
29
+ #include <functional>
30
+ #include <memory>
31
+ #include <bitset> // std::bitset
32
+ #include <jsoncons/conv_error.hpp>
33
+ #include <jsoncons/value_converter.hpp>
34
+
35
+ #if defined(JSONCONS_HAS_STD_VARIANT)
36
+ #include <variant>
37
+ #endif
38
+
39
+ namespace jsoncons {
40
+
41
+ template <class T>
42
+ struct is_json_type_traits_declared : public std::false_type
43
+ {};
44
+
45
+ #if !defined(JSONCONS_NO_DEPRECATED)
46
+ template <class T>
47
+ using is_json_type_traits_impl = is_json_type_traits_declared<T>;
48
+ #endif
49
+
50
+ // json_type_traits
51
+
52
+ template<typename T>
53
+ struct unimplemented : std::false_type
54
+ {};
55
+
56
+ template <class Json, class T, class Enable=void>
57
+ struct json_type_traits
58
+ {
59
+ using allocator_type = typename Json::allocator_type;
60
+
61
+ static constexpr bool is_compatible = false;
62
+
63
+ static constexpr bool is(const Json&) noexcept
64
+ {
65
+ return false;
66
+ }
67
+
68
+ static T as(const Json&)
69
+ {
70
+ static_assert(unimplemented<T>::value, "as not implemented");
71
+ }
72
+
73
+ static Json to_json(const T&, const allocator_type& = allocator_type())
74
+ {
75
+ static_assert(unimplemented<T>::value, "to_json not implemented");
76
+ }
77
+ };
78
+
79
+ namespace detail {
80
+
81
+ template<class Json, class T>
82
+ using
83
+ traits_can_convert_t = decltype(json_type_traits<Json,T>::can_convert(Json()));
84
+
85
+ template<class Json, class T>
86
+ using
87
+ has_can_convert = traits_extension::is_detected<traits_can_convert_t, Json, T>;
88
+
89
+ template <class T>
90
+ struct invoke_can_convert
91
+ {
92
+ template <class Json>
93
+ static
94
+ typename std::enable_if<has_can_convert<Json,T>::value,bool>::type
95
+ can_convert(const Json& j) noexcept
96
+ {
97
+ return json_type_traits<Json,T>::can_convert(j);
98
+ }
99
+ template <class Json>
100
+ static
101
+ typename std::enable_if<!has_can_convert<Json,T>::value,bool>::type
102
+ can_convert(const Json& j) noexcept
103
+ {
104
+ return json_type_traits<Json,T>::is(j);
105
+ }
106
+ };
107
+
108
+ // is_json_type_traits_unspecialized
109
+ template<class Json, class T, class Enable = void>
110
+ struct is_json_type_traits_unspecialized : std::false_type {};
111
+
112
+ // is_json_type_traits_unspecialized
113
+ template<class Json, class T>
114
+ struct is_json_type_traits_unspecialized<Json,T,
115
+ typename std::enable_if<!std::integral_constant<bool, json_type_traits<Json, T>::is_compatible>::value>::type
116
+ > : std::true_type {};
117
+
118
+ // is_compatible_array_type
119
+ template<class Json, class T, class Enable=void>
120
+ struct is_compatible_array_type : std::false_type {};
121
+
122
+ template<class Json, class T>
123
+ struct is_compatible_array_type<Json,T,
124
+ typename std::enable_if<!std::is_same<T,typename Json::array>::value &&
125
+ traits_extension::is_list_like<T>::value &&
126
+ !is_json_type_traits_unspecialized<Json,typename std::iterator_traits<typename T::iterator>::value_type>::value
127
+ >::type> : std::true_type {};
128
+
129
+ } // namespace detail
130
+
131
+ // is_json_type_traits_specialized
132
+ template<class Json, class T, class Enable=void>
133
+ struct is_json_type_traits_specialized : std::false_type {};
134
+
135
+ template<class Json, class T>
136
+ struct is_json_type_traits_specialized<Json,T,
137
+ typename std::enable_if<!jsoncons::detail::is_json_type_traits_unspecialized<Json,T>::value
138
+ >::type> : std::true_type {};
139
+
140
+ template<class Json>
141
+ struct json_type_traits<Json, const typename std::decay<typename Json::char_type>::type*>
142
+ {
143
+ using char_type = typename Json::char_type;
144
+ using allocator_type = typename Json::allocator_type;
145
+
146
+ static bool is(const Json& j) noexcept
147
+ {
148
+ return j.is_string();
149
+ }
150
+ static const char_type* as(const Json& j)
151
+ {
152
+ return j.as_cstring();
153
+ }
154
+ template <class ... Args>
155
+ static Json to_json(const char_type* s, Args&&... args)
156
+ {
157
+ return Json(s, semantic_tag::none, std::forward<Args>(args)...);
158
+ }
159
+ };
160
+
161
+ template<class Json>
162
+ struct json_type_traits<Json, typename std::decay<typename Json::char_type>::type*>
163
+ {
164
+ using char_type = typename Json::char_type;
165
+ using allocator_type = typename Json::allocator_type;
166
+
167
+ static bool is(const Json& j) noexcept
168
+ {
169
+ return j.is_string();
170
+ }
171
+ template <class ... Args>
172
+ static Json to_json(const char_type* s, Args&&... args)
173
+ {
174
+ return Json(s, semantic_tag::none, std::forward<Args>(args)...);
175
+ }
176
+ };
177
+
178
+ // integer
179
+
180
+ template<class Json, class T>
181
+ struct json_type_traits<Json, T,
182
+ typename std::enable_if<traits_extension::is_integer<T>::value
183
+ >::type>
184
+ {
185
+ using allocator_type = typename Json::allocator_type;
186
+
187
+ static bool is(const Json& j) noexcept
188
+ {
189
+ return j.template is_integer<T>();
190
+ }
191
+ static T as(const Json& j)
192
+ {
193
+ return j.template as_integer<T>();
194
+ }
195
+
196
+ static Json to_json(T val, allocator_type alloc = allocator_type())
197
+ {
198
+ return Json(val, semantic_tag::none, alloc);
199
+ }
200
+ };
201
+
202
+ template<class Json, class T>
203
+ struct json_type_traits<Json, T,
204
+ typename std::enable_if<std::is_floating_point<T>::value
205
+ >::type>
206
+ {
207
+ using allocator_type = typename Json::allocator_type;
208
+
209
+ static bool is(const Json& j) noexcept
210
+ {
211
+ return j.is_double();
212
+ }
213
+ static T as(const Json& j)
214
+ {
215
+ return static_cast<T>(j.as_double());
216
+ }
217
+ static Json to_json(T val, allocator_type = allocator_type())
218
+ {
219
+ return Json(val, semantic_tag::none);
220
+ }
221
+ };
222
+
223
+ template<class Json>
224
+ struct json_type_traits<Json, typename Json::object>
225
+ {
226
+ using json_object = typename Json::object;
227
+ using allocator_type = typename Json::allocator_type;
228
+
229
+ static bool is(const Json& j) noexcept
230
+ {
231
+ return j.is_object();
232
+ }
233
+ static Json to_json(const json_object& o, const allocator_type& = allocator_type())
234
+ {
235
+ return Json(o,semantic_tag::none);
236
+ }
237
+ };
238
+
239
+ template<class Json>
240
+ struct json_type_traits<Json, typename Json::array>
241
+ {
242
+ using json_array = typename Json::array;
243
+ using allocator_type = typename Json::allocator_type;
244
+
245
+ static bool is(const Json& j) noexcept
246
+ {
247
+ return j.is_array();
248
+ }
249
+ static Json to_json(const json_array& a, const allocator_type& = allocator_type())
250
+ {
251
+ return Json(a, semantic_tag::none);
252
+ }
253
+ };
254
+
255
+ template<class Json>
256
+ struct json_type_traits<Json, Json>
257
+ {
258
+ using allocator_type = typename Json::allocator_type;
259
+
260
+ static bool is(const Json&) noexcept
261
+ {
262
+ return true;
263
+ }
264
+ static Json as(Json j)
265
+ {
266
+ return j;
267
+ }
268
+ static Json to_json(const Json& val, allocator_type = allocator_type())
269
+ {
270
+ return val;
271
+ }
272
+ };
273
+
274
+ template<class Json>
275
+ struct json_type_traits<Json, jsoncons::null_type>
276
+ {
277
+ using allocator_type = typename Json::allocator_type;
278
+
279
+ static bool is(const Json& j) noexcept
280
+ {
281
+ return j.is_null();
282
+ }
283
+ static typename jsoncons::null_type as(const Json& j)
284
+ {
285
+ if (!j.is_null())
286
+ {
287
+ JSONCONS_THROW(conv_error(conv_errc::not_jsoncons_null_type));
288
+ }
289
+ return jsoncons::null_type();
290
+ }
291
+ static Json to_json(jsoncons::null_type, allocator_type = allocator_type())
292
+ {
293
+ return Json::null();
294
+ }
295
+ };
296
+
297
+ template<class Json>
298
+ struct json_type_traits<Json, bool>
299
+ {
300
+ using allocator_type = typename Json::allocator_type;
301
+
302
+ static bool is(const Json& j) noexcept
303
+ {
304
+ return j.is_bool();
305
+ }
306
+ static bool as(const Json& j)
307
+ {
308
+ return j.as_bool();
309
+ }
310
+ static Json to_json(bool val, allocator_type = allocator_type())
311
+ {
312
+ return Json(val, semantic_tag::none);
313
+ }
314
+ };
315
+
316
+ template<class Json, class T>
317
+ struct json_type_traits<Json, T, typename std::enable_if<std::is_same<T,
318
+ std::conditional<!std::is_same<bool,std::vector<bool>::const_reference>::value,
319
+ std::vector<bool>::const_reference,
320
+ void>::type>::value>::type>
321
+ {
322
+ using allocator_type = typename Json::allocator_type;
323
+
324
+ static bool is(const Json& j) noexcept
325
+ {
326
+ return j.is_bool();
327
+ }
328
+ static bool as(const Json& j)
329
+ {
330
+ return j.as_bool();
331
+ }
332
+ static Json to_json(bool val, allocator_type = allocator_type())
333
+ {
334
+ return Json(val, semantic_tag::none);
335
+ }
336
+ };
337
+
338
+ template<class Json>
339
+ struct json_type_traits<Json, std::vector<bool>::reference>
340
+ {
341
+ using allocator_type = typename Json::allocator_type;
342
+
343
+ static bool is(const Json& j) noexcept
344
+ {
345
+ return j.is_bool();
346
+ }
347
+ static bool as(const Json& j)
348
+ {
349
+ return j.as_bool();
350
+ }
351
+ static Json to_json(bool val, allocator_type = allocator_type())
352
+ {
353
+ return Json(val, semantic_tag::none);
354
+ }
355
+ };
356
+
357
+ template<class Json, typename T>
358
+ struct json_type_traits<Json, T,
359
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
360
+ traits_extension::is_string<T>::value &&
361
+ std::is_same<typename Json::char_type,typename T::value_type>::value>::type>
362
+ {
363
+ using allocator_type = typename Json::allocator_type;
364
+
365
+ static bool is(const Json& j) noexcept
366
+ {
367
+ return j.is_string();
368
+ }
369
+
370
+ static T as(const Json& j)
371
+ {
372
+ return T(j.as_string());
373
+ }
374
+
375
+ static Json to_json(const T& val)
376
+ {
377
+ return Json(val, semantic_tag::none);
378
+ }
379
+
380
+ static Json to_json(const T& val, const allocator_type& alloc)
381
+ {
382
+ return Json(val, semantic_tag::none, alloc);
383
+ }
384
+ };
385
+
386
+ template<class Json, typename T>
387
+ struct json_type_traits<Json, T,
388
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
389
+ traits_extension::is_string<T>::value &&
390
+ !std::is_same<typename Json::char_type,typename T::value_type>::value>::type>
391
+ {
392
+ using char_type = typename Json::char_type;
393
+ using allocator_type = typename Json::allocator_type;
394
+
395
+ static bool is(const Json& j) noexcept
396
+ {
397
+ return j.is_string();
398
+ }
399
+
400
+ static T as(const Json& j)
401
+ {
402
+ auto s = j.as_string();
403
+ T val;
404
+ unicode_traits::convert(s.data(), s.size(), val);
405
+ return val;
406
+ }
407
+
408
+ static Json to_json(const T& val)
409
+ {
410
+ std::basic_string<char_type> s;
411
+ unicode_traits::convert(val.data(), val.size(), s);
412
+
413
+ return Json(s, semantic_tag::none);
414
+ }
415
+
416
+ static Json to_json(const T& val, const allocator_type& alloc)
417
+ {
418
+ std::basic_string<char_type> s;
419
+ unicode_traits::convert(val.data(), val.size(), s);
420
+ return Json(s, semantic_tag::none, alloc);
421
+ }
422
+ };
423
+
424
+ template<class Json, typename T>
425
+ struct json_type_traits<Json, T,
426
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
427
+ traits_extension::is_string_view<T>::value &&
428
+ std::is_same<typename Json::char_type,typename T::value_type>::value>::type>
429
+ {
430
+ using allocator_type = typename Json::allocator_type;
431
+
432
+ static bool is(const Json& j) noexcept
433
+ {
434
+ return j.is_string_view();
435
+ }
436
+
437
+ static T as(const Json& j)
438
+ {
439
+ return T(j.as_string_view().data(),j.as_string_view().size());
440
+ }
441
+
442
+ static Json to_json(const T& val)
443
+ {
444
+ return Json(val, semantic_tag::none);
445
+ }
446
+
447
+ static Json to_json(const T& val, const allocator_type& alloc)
448
+ {
449
+ return Json(val, semantic_tag::none, alloc);
450
+ }
451
+ };
452
+
453
+ // array back insertable
454
+
455
+ template<class Json, typename T>
456
+ struct json_type_traits<Json, T,
457
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
458
+ jsoncons::detail::is_compatible_array_type<Json,T>::value &&
459
+ traits_extension::is_back_insertable<T>::value
460
+ >::type>
461
+ {
462
+ typedef typename std::iterator_traits<typename T::iterator>::value_type value_type;
463
+ using allocator_type = typename Json::allocator_type;
464
+
465
+ static bool is(const Json& j) noexcept
466
+ {
467
+ bool result = j.is_array();
468
+ if (result)
469
+ {
470
+ for (auto e : j.array_range())
471
+ {
472
+ if (!e.template is<value_type>())
473
+ {
474
+ result = false;
475
+ break;
476
+ }
477
+ }
478
+ }
479
+ return result;
480
+ }
481
+
482
+ // array back insertable non-byte container
483
+
484
+ template <class Container = T>
485
+ static typename std::enable_if<!traits_extension::is_byte<typename Container::value_type>::value,Container>::type
486
+ as(const Json& j)
487
+ {
488
+ if (j.is_array())
489
+ {
490
+ T result;
491
+ visit_reserve_(typename std::integral_constant<bool, traits_extension::has_reserve<T>::value>::type(),result,j.size());
492
+ for (const auto& item : j.array_range())
493
+ {
494
+ result.push_back(item.template as<value_type>());
495
+ }
496
+
497
+ return result;
498
+ }
499
+ else
500
+ {
501
+ JSONCONS_THROW(conv_error(conv_errc::not_vector));
502
+ }
503
+ }
504
+
505
+ // array back insertable byte container
506
+
507
+ template <class Container = T>
508
+ static typename std::enable_if<traits_extension::is_byte<typename Container::value_type>::value,Container>::type
509
+ as(const Json& j)
510
+ {
511
+ std::error_code ec;
512
+ if (j.is_array())
513
+ {
514
+ T result;
515
+ visit_reserve_(typename std::integral_constant<bool, traits_extension::has_reserve<T>::value>::type(),result,j.size());
516
+ for (const auto& item : j.array_range())
517
+ {
518
+ result.push_back(item.template as<value_type>());
519
+ }
520
+
521
+ return result;
522
+ }
523
+ else if (j.is_byte_string_view())
524
+ {
525
+ value_converter<byte_string_view,T> converter;
526
+ auto v = converter.convert(j.as_byte_string_view(),j.tag(), ec);
527
+ if (ec)
528
+ {
529
+ JSONCONS_THROW(conv_error(ec));
530
+ }
531
+ return v;
532
+ }
533
+ else if (j.is_string())
534
+ {
535
+ value_converter<basic_string_view<char>,T> converter;
536
+ auto v = converter.convert(j.as_string_view(),j.tag(), ec);
537
+ if (ec)
538
+ {
539
+ JSONCONS_THROW(conv_error(ec));
540
+ }
541
+ return v;
542
+ }
543
+ else
544
+ {
545
+ JSONCONS_THROW(conv_error(conv_errc::not_vector));
546
+ }
547
+ }
548
+
549
+ template <class Container = T>
550
+ static typename std::enable_if<!traits_extension::is_std_byte<typename Container::value_type>::value,Json>::type
551
+ to_json(const T& val)
552
+ {
553
+ Json j(json_array_arg);
554
+ auto first = std::begin(val);
555
+ auto last = std::end(val);
556
+ std::size_t size = std::distance(first,last);
557
+ j.reserve(size);
558
+ for (auto it = first; it != last; ++it)
559
+ {
560
+ j.push_back(*it);
561
+ }
562
+ return j;
563
+ }
564
+
565
+ template <class Container = T>
566
+ static typename std::enable_if<!traits_extension::is_std_byte<typename Container::value_type>::value,Json>::type
567
+ to_json(const T& val, const allocator_type& alloc)
568
+ {
569
+ Json j(json_array_arg, alloc);
570
+ auto first = std::begin(val);
571
+ auto last = std::end(val);
572
+ std::size_t size = std::distance(first, last);
573
+ j.reserve(size);
574
+ for (auto it = first; it != last; ++it)
575
+ {
576
+ j.push_back(*it);
577
+ }
578
+ return j;
579
+ }
580
+
581
+ template <class Container = T>
582
+ static typename std::enable_if<traits_extension::is_std_byte<typename Container::value_type>::value,Json>::type
583
+ to_json(const T& val)
584
+ {
585
+ Json j(byte_string_arg, val);
586
+ return j;
587
+ }
588
+
589
+ template <class Container = T>
590
+ static typename std::enable_if<traits_extension::is_std_byte<typename Container::value_type>::value,Json>::type
591
+ to_json(const T& val, const allocator_type& alloc)
592
+ {
593
+ Json j(byte_string_arg, val, semantic_tag::none, alloc);
594
+ return j;
595
+ }
596
+
597
+ static void visit_reserve_(std::true_type, T& v, std::size_t size)
598
+ {
599
+ v.reserve(size);
600
+ }
601
+
602
+ static void visit_reserve_(std::false_type, T&, std::size_t)
603
+ {
604
+ }
605
+ };
606
+
607
+ // array, not back insertable but insertable
608
+
609
+ template<class Json, typename T>
610
+ struct json_type_traits<Json, T,
611
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
612
+ jsoncons::detail::is_compatible_array_type<Json,T>::value &&
613
+ !traits_extension::is_back_insertable<T>::value &&
614
+ traits_extension::is_insertable<T>::value>::type>
615
+ {
616
+ typedef typename std::iterator_traits<typename T::iterator>::value_type value_type;
617
+ using allocator_type = typename Json::allocator_type;
618
+
619
+ static bool is(const Json& j) noexcept
620
+ {
621
+ bool result = j.is_array();
622
+ if (result)
623
+ {
624
+ for (auto e : j.array_range())
625
+ {
626
+ if (!e.template is<value_type>())
627
+ {
628
+ result = false;
629
+ break;
630
+ }
631
+ }
632
+ }
633
+ return result;
634
+ }
635
+
636
+ static T as(const Json& j)
637
+ {
638
+ if (j.is_array())
639
+ {
640
+ T result;
641
+ for (const auto& item : j.array_range())
642
+ {
643
+ result.insert(item.template as<value_type>());
644
+ }
645
+
646
+ return result;
647
+ }
648
+ else
649
+ {
650
+ JSONCONS_THROW(conv_error(conv_errc::not_vector));
651
+ }
652
+ }
653
+
654
+ static Json to_json(const T& val)
655
+ {
656
+ Json j(json_array_arg);
657
+ auto first = std::begin(val);
658
+ auto last = std::end(val);
659
+ std::size_t size = std::distance(first,last);
660
+ j.reserve(size);
661
+ for (auto it = first; it != last; ++it)
662
+ {
663
+ j.push_back(*it);
664
+ }
665
+ return j;
666
+ }
667
+
668
+ static Json to_json(const T& val, const allocator_type& alloc)
669
+ {
670
+ Json j(json_array_arg, alloc);
671
+ auto first = std::begin(val);
672
+ auto last = std::end(val);
673
+ std::size_t size = std::distance(first, last);
674
+ j.reserve(size);
675
+ for (auto it = first; it != last; ++it)
676
+ {
677
+ j.push_back(*it);
678
+ }
679
+ return j;
680
+ }
681
+ };
682
+
683
+ // array not back insertable or insertable, but front insertable
684
+
685
+ template<class Json, typename T>
686
+ struct json_type_traits<Json, T,
687
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
688
+ jsoncons::detail::is_compatible_array_type<Json,T>::value &&
689
+ !traits_extension::is_back_insertable<T>::value &&
690
+ !traits_extension::is_insertable<T>::value &&
691
+ traits_extension::is_front_insertable<T>::value>::type>
692
+ {
693
+ typedef typename std::iterator_traits<typename T::iterator>::value_type value_type;
694
+ using allocator_type = typename Json::allocator_type;
695
+
696
+ static bool is(const Json& j) noexcept
697
+ {
698
+ bool result = j.is_array();
699
+ if (result)
700
+ {
701
+ for (auto e : j.array_range())
702
+ {
703
+ if (!e.template is<value_type>())
704
+ {
705
+ result = false;
706
+ break;
707
+ }
708
+ }
709
+ }
710
+ return result;
711
+ }
712
+
713
+ static T as(const Json& j)
714
+ {
715
+ if (j.is_array())
716
+ {
717
+ T result;
718
+
719
+ auto it = j.array_range().rbegin();
720
+ auto end = j.array_range().rend();
721
+ for (; it != end; ++it)
722
+ {
723
+ result.push_front((*it).template as<value_type>());
724
+ }
725
+
726
+ return result;
727
+ }
728
+ else
729
+ {
730
+ JSONCONS_THROW(conv_error(conv_errc::not_vector));
731
+ }
732
+ }
733
+
734
+ static Json to_json(const T& val)
735
+ {
736
+ Json j(json_array_arg);
737
+ auto first = std::begin(val);
738
+ auto last = std::end(val);
739
+ std::size_t size = std::distance(first,last);
740
+ j.reserve(size);
741
+ for (auto it = first; it != last; ++it)
742
+ {
743
+ j.push_back(*it);
744
+ }
745
+ return j;
746
+ }
747
+
748
+ static Json to_json(const T& val, const allocator_type& alloc)
749
+ {
750
+ Json j(json_array_arg, alloc);
751
+ auto first = std::begin(val);
752
+ auto last = std::end(val);
753
+ std::size_t size = std::distance(first, last);
754
+ j.reserve(size);
755
+ for (auto it = first; it != last; ++it)
756
+ {
757
+ j.push_back(*it);
758
+ }
759
+ return j;
760
+ }
761
+ };
762
+
763
+ // std::array
764
+
765
+ template<class Json, class E, std::size_t N>
766
+ struct json_type_traits<Json, std::array<E, N>>
767
+ {
768
+ using allocator_type = typename Json::allocator_type;
769
+
770
+ using value_type = E;
771
+
772
+ static bool is(const Json& j) noexcept
773
+ {
774
+ bool result = j.is_array() && j.size() == N;
775
+ if (result)
776
+ {
777
+ for (auto e : j.array_range())
778
+ {
779
+ if (!e.template is<value_type>())
780
+ {
781
+ result = false;
782
+ break;
783
+ }
784
+ }
785
+ }
786
+ return result;
787
+ }
788
+
789
+ static std::array<E, N> as(const Json& j)
790
+ {
791
+ std::array<E, N> buff;
792
+ if (j.size() != N)
793
+ {
794
+ JSONCONS_THROW(conv_error(conv_errc::not_array));
795
+ }
796
+ for (std::size_t i = 0; i < N; i++)
797
+ {
798
+ buff[i] = j[i].template as<E>();
799
+ }
800
+ return buff;
801
+ }
802
+
803
+ static Json to_json(const std::array<E, N>& val)
804
+ {
805
+ Json j(json_array_arg);
806
+ j.reserve(N);
807
+ for (auto it = val.begin(); it != val.end(); ++it)
808
+ {
809
+ j.push_back(*it);
810
+ }
811
+ return j;
812
+ }
813
+
814
+ static Json to_json(const std::array<E, N>& val,
815
+ const allocator_type& alloc)
816
+ {
817
+ Json j(json_array_arg, alloc);
818
+ j.reserve(N);
819
+ for (auto it = val.begin(); it != val.end(); ++it)
820
+ {
821
+ j.push_back(*it);
822
+ }
823
+ return j;
824
+ }
825
+ };
826
+
827
+ // map like
828
+ template<class Json, typename T>
829
+ struct json_type_traits<Json, T,
830
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
831
+ traits_extension::is_map_like<T>::value &&
832
+ traits_extension::is_constructible_from_const_pointer_and_size<typename T::key_type>::value &&
833
+ is_json_type_traits_specialized<Json,typename T::mapped_type>::value>::type
834
+ >
835
+ {
836
+ using mapped_type = typename T::mapped_type;
837
+ using value_type = typename T::value_type;
838
+ using key_type = typename T::key_type;
839
+ using allocator_type = typename Json::allocator_type;
840
+
841
+ static bool is(const Json& j) noexcept
842
+ {
843
+ bool result = j.is_object();
844
+ for (auto member : j.object_range())
845
+ {
846
+ if (!member.value().template is<mapped_type>())
847
+ {
848
+ result = false;
849
+ }
850
+ }
851
+ return result;
852
+ }
853
+
854
+ static T as(const Json& j)
855
+ {
856
+ if (!j.is_object())
857
+ {
858
+ JSONCONS_THROW(conv_error(conv_errc::not_map));
859
+ }
860
+ T result;
861
+ for (const auto& item : j.object_range())
862
+ {
863
+ result.emplace(key_type(item.key().data(),item.key().size()), item.value().template as<mapped_type>());
864
+ }
865
+
866
+ return result;
867
+ }
868
+
869
+ static Json to_json(const T& val)
870
+ {
871
+ Json j(json_object_arg, val.begin(), val.end());
872
+ return j;
873
+ }
874
+
875
+ static Json to_json(const T& val, const allocator_type& alloc)
876
+ {
877
+ Json j(json_object_arg, val.begin(), val.end(), alloc);
878
+ return j;
879
+ }
880
+ };
881
+
882
+ template <class Json, typename T>
883
+ struct json_type_traits<Json, T,
884
+ typename std::enable_if<!is_json_type_traits_declared<T>::value &&
885
+ traits_extension::is_map_like<T>::value &&
886
+ !traits_extension::is_constructible_from_const_pointer_and_size<typename T::key_type>::value &&
887
+ is_json_type_traits_specialized<Json,typename T::key_type>::value &&
888
+ is_json_type_traits_specialized<Json,typename T::mapped_type>::value>::type
889
+ >
890
+ {
891
+ using mapped_type = typename T::mapped_type;
892
+ using value_type = typename T::value_type;
893
+ using key_type = typename T::key_type;
894
+ using allocator_type = typename Json::allocator_type;
895
+
896
+ static bool is(const Json& val) noexcept
897
+ {
898
+ if (!val.is_object())
899
+ return false;
900
+ for (const auto& item : val.object_range())
901
+ {
902
+ Json j(item.key());
903
+ if (!j.template is<key_type>())
904
+ {
905
+ return false;
906
+ }
907
+ if (!item.value().template is<mapped_type>())
908
+ {
909
+ return false;
910
+ }
911
+ }
912
+ return true;
913
+ }
914
+
915
+ static T as(const Json& val)
916
+ {
917
+ T result;
918
+ for (const auto& item : val.object_range())
919
+ {
920
+ Json j(item.key());
921
+ auto key = json_type_traits<Json,key_type>::as(j);
922
+ result.emplace(std::move(key), item.value().template as<mapped_type>());
923
+ }
924
+
925
+ return result;
926
+ }
927
+
928
+ static Json to_json(const T& val)
929
+ {
930
+ Json j(json_object_arg);
931
+ j.reserve(val.size());
932
+ for (const auto& item : val)
933
+ {
934
+ auto temp = json_type_traits<Json,key_type>::to_json(item.first);
935
+ typename Json::key_type key;
936
+ temp.dump(key);
937
+ j.try_emplace(std::move(key), item.second);
938
+ }
939
+ return j;
940
+ }
941
+
942
+ static Json to_json(const T& val, const allocator_type& alloc)
943
+ {
944
+ Json j(json_object_arg, semantic_tag::none, alloc);
945
+ j.reserve(val.size());
946
+ for (const auto& item : val)
947
+ {
948
+ auto temp = json_type_traits<Json,key_type>::to_json(item.first, alloc);
949
+ typename Json::key_type key(alloc);
950
+ temp.dump(key);
951
+ j.try_emplace(std::move(key), item.second, alloc);
952
+ }
953
+ return j;
954
+ }
955
+ };
956
+
957
+ namespace tuple_detail
958
+ {
959
+ template<size_t Pos, std::size_t Size, class Json, class Tuple>
960
+ struct json_tuple_helper
961
+ {
962
+ using element_type = typename std::tuple_element<Size-Pos, Tuple>::type;
963
+ using next = json_tuple_helper<Pos-1, Size, Json, Tuple>;
964
+
965
+ static bool is(const Json& j) noexcept
966
+ {
967
+ if (j[Size-Pos].template is<element_type>())
968
+ {
969
+ return next::is(j);
970
+ }
971
+ else
972
+ {
973
+ return false;
974
+ }
975
+ }
976
+
977
+ static void as(Tuple& tuple, const Json& j)
978
+ {
979
+ std::get<Size-Pos>(tuple) = j[Size-Pos].template as<element_type>();
980
+ next::as(tuple, j);
981
+ }
982
+
983
+ static void to_json(const Tuple& tuple, Json& j)
984
+ {
985
+ j.push_back(json_type_traits<Json, element_type>::to_json(std::get<Size-Pos>(tuple)));
986
+ next::to_json(tuple, j);
987
+ }
988
+ };
989
+
990
+ template<size_t Size, class Json, class Tuple>
991
+ struct json_tuple_helper<0, Size, Json, Tuple>
992
+ {
993
+ static bool is(const Json&) noexcept
994
+ {
995
+ return true;
996
+ }
997
+
998
+ static void as(Tuple&, const Json&)
999
+ {
1000
+ }
1001
+
1002
+ static void to_json(const Tuple&, Json&)
1003
+ {
1004
+ }
1005
+ };
1006
+ } // namespace detail
1007
+
1008
+ template<class Json, typename... E>
1009
+ struct json_type_traits<Json, std::tuple<E...>>
1010
+ {
1011
+ private:
1012
+ using helper = tuple_detail::json_tuple_helper<sizeof...(E), sizeof...(E), Json, std::tuple<E...>>;
1013
+
1014
+ public:
1015
+ using allocator_type = typename Json::allocator_type;
1016
+
1017
+ static bool is(const Json& j) noexcept
1018
+ {
1019
+ return helper::is(j);
1020
+ }
1021
+
1022
+ static std::tuple<E...> as(const Json& j)
1023
+ {
1024
+ std::tuple<E...> buff;
1025
+ helper::as(buff, j);
1026
+ return buff;
1027
+ }
1028
+
1029
+ static Json to_json(const std::tuple<E...>& val)
1030
+ {
1031
+ Json j(json_array_arg);
1032
+ j.reserve(sizeof...(E));
1033
+ helper::to_json(val, j);
1034
+ return j;
1035
+ }
1036
+
1037
+ static Json to_json(const std::tuple<E...>& val,
1038
+ const allocator_type& alloc)
1039
+ {
1040
+ Json j(json_array_arg, alloc);
1041
+ j.reserve(sizeof...(E));
1042
+ helper::to_json(val, j);
1043
+ return j;
1044
+ }
1045
+ };
1046
+
1047
+ template<class Json, class T1, class T2>
1048
+ struct json_type_traits<Json, std::pair<T1,T2>>
1049
+ {
1050
+ public:
1051
+ using allocator_type = typename Json::allocator_type;
1052
+
1053
+ static bool is(const Json& j) noexcept
1054
+ {
1055
+ return j.is_array() && j.size() == 2;
1056
+ }
1057
+
1058
+ static std::pair<T1,T2> as(const Json& j)
1059
+ {
1060
+ return std::make_pair<T1,T2>(j[0].template as<T1>(),j[1].template as<T2>());
1061
+ }
1062
+
1063
+ static Json to_json(const std::pair<T1,T2>& val)
1064
+ {
1065
+ Json j(json_array_arg);
1066
+ j.reserve(2);
1067
+ j.push_back(val.first);
1068
+ j.push_back(val.second);
1069
+ return j;
1070
+ }
1071
+
1072
+ static Json to_json(const std::pair<T1, T2>& val, const allocator_type& alloc)
1073
+ {
1074
+ Json j(json_array_arg, alloc);
1075
+ j.reserve(2);
1076
+ j.push_back(val.first);
1077
+ j.push_back(val.second);
1078
+ return j;
1079
+ }
1080
+ };
1081
+
1082
+ template<class Json, class T>
1083
+ struct json_type_traits<Json, T,
1084
+ typename std::enable_if<traits_extension::is_basic_byte_string<T>::value>::type>
1085
+ {
1086
+ public:
1087
+ using allocator_type = typename Json::allocator_type;
1088
+
1089
+ static bool is(const Json& j) noexcept
1090
+ {
1091
+ return j.is_byte_string();
1092
+ }
1093
+
1094
+ static T as(const Json& j)
1095
+ {
1096
+ return j.template as_byte_string<typename T::allocator_type>();
1097
+ }
1098
+
1099
+ static Json to_json(const T& val,
1100
+ const allocator_type& alloc = allocator_type())
1101
+ {
1102
+ return Json(byte_string_arg, val, semantic_tag::none, alloc);
1103
+ }
1104
+ };
1105
+
1106
+ template<class Json, class ValueType>
1107
+ struct json_type_traits<Json, std::shared_ptr<ValueType>,
1108
+ typename std::enable_if<!is_json_type_traits_declared<std::shared_ptr<ValueType>>::value &&
1109
+ !std::is_polymorphic<ValueType>::value
1110
+ >::type>
1111
+ {
1112
+ static bool is(const Json& j) noexcept
1113
+ {
1114
+ return j.is_null() || j.template is<ValueType>();
1115
+ }
1116
+
1117
+ static std::shared_ptr<ValueType> as(const Json& j)
1118
+ {
1119
+ return j.is_null() ? std::shared_ptr<ValueType>(nullptr) : std::make_shared<ValueType>(j.template as<ValueType>());
1120
+ }
1121
+
1122
+ static Json to_json(const std::shared_ptr<ValueType>& ptr)
1123
+ {
1124
+ if (ptr.get() != nullptr)
1125
+ {
1126
+ Json j(*ptr);
1127
+ return j;
1128
+ }
1129
+ else
1130
+ {
1131
+ return Json::null();
1132
+ }
1133
+ }
1134
+ };
1135
+
1136
+ template<class Json, class ValueType>
1137
+ struct json_type_traits<Json, std::unique_ptr<ValueType>,
1138
+ typename std::enable_if<!is_json_type_traits_declared<std::unique_ptr<ValueType>>::value &&
1139
+ !std::is_polymorphic<ValueType>::value
1140
+ >::type>
1141
+ {
1142
+ static bool is(const Json& j) noexcept
1143
+ {
1144
+ return j.is_null() || j.template is<ValueType>();
1145
+ }
1146
+
1147
+ static std::unique_ptr<ValueType> as(const Json& j)
1148
+ {
1149
+ return j.is_null() ? std::unique_ptr<ValueType>(nullptr) : jsoncons::make_unique<ValueType>(j.template as<ValueType>());
1150
+ }
1151
+
1152
+ static Json to_json(const std::unique_ptr<ValueType>& ptr)
1153
+ {
1154
+ if (ptr.get() != nullptr)
1155
+ {
1156
+ Json j(*ptr);
1157
+ return j;
1158
+ }
1159
+ else
1160
+ {
1161
+ return Json::null();
1162
+ }
1163
+ }
1164
+ };
1165
+
1166
+ template<class Json, class T>
1167
+ struct json_type_traits<Json, jsoncons::optional<T>,
1168
+ typename std::enable_if<!is_json_type_traits_declared<jsoncons::optional<T>>::value>::type>
1169
+ {
1170
+ public:
1171
+ static bool is(const Json& j) noexcept
1172
+ {
1173
+ return j.is_null() || j.template is<T>();
1174
+ }
1175
+
1176
+ static jsoncons::optional<T> as(const Json& j)
1177
+ {
1178
+ return j.is_null() ? jsoncons::optional<T>() : jsoncons::optional<T>(j.template as<T>());
1179
+ }
1180
+
1181
+ static Json to_json(const jsoncons::optional<T>& val)
1182
+ {
1183
+ return val.has_value() ? Json(*val) : Json::null();
1184
+ }
1185
+ };
1186
+
1187
+ template<class Json>
1188
+ struct json_type_traits<Json, byte_string_view>
1189
+ {
1190
+ using allocator_type = typename Json::allocator_type;
1191
+
1192
+ public:
1193
+ static bool is(const Json& j) noexcept
1194
+ {
1195
+ return j.is_byte_string_view();
1196
+ }
1197
+
1198
+ static byte_string_view as(const Json& j)
1199
+ {
1200
+ return j.as_byte_string_view();
1201
+ }
1202
+
1203
+ static Json to_json(const byte_string_view& val, const allocator_type& alloc = allocator_type())
1204
+ {
1205
+ return Json(byte_string_arg, val, semantic_tag::none, alloc);
1206
+ }
1207
+ };
1208
+
1209
+ // basic_bigint
1210
+
1211
+ template<class Json, class Allocator>
1212
+ struct json_type_traits<Json, basic_bigint<Allocator>>
1213
+ {
1214
+ public:
1215
+ using char_type = typename Json::char_type;
1216
+
1217
+ static bool is(const Json& j) noexcept
1218
+ {
1219
+ switch (j.type())
1220
+ {
1221
+ case json_type::string_value:
1222
+ return jsoncons::detail::is_base10(j.as_string_view().data(), j.as_string_view().length());
1223
+ case json_type::int64_value:
1224
+ case json_type::uint64_value:
1225
+ return true;
1226
+ default:
1227
+ return false;
1228
+ }
1229
+ }
1230
+
1231
+ static basic_bigint<Allocator> as(const Json& j)
1232
+ {
1233
+ switch (j.type())
1234
+ {
1235
+ case json_type::string_value:
1236
+ if (!jsoncons::detail::is_base10(j.as_string_view().data(), j.as_string_view().length()))
1237
+ {
1238
+ JSONCONS_THROW(conv_error(conv_errc::not_bigint));
1239
+ }
1240
+ return basic_bigint<Allocator>::from_string(j.as_string_view().data(), j.as_string_view().length());
1241
+ case json_type::half_value:
1242
+ case json_type::double_value:
1243
+ return basic_bigint<Allocator>(j.template as<int64_t>());
1244
+ case json_type::int64_value:
1245
+ return basic_bigint<Allocator>(j.template as<int64_t>());
1246
+ case json_type::uint64_value:
1247
+ return basic_bigint<Allocator>(j.template as<uint64_t>());
1248
+ default:
1249
+ JSONCONS_THROW(conv_error(conv_errc::not_bigint));
1250
+ }
1251
+ }
1252
+
1253
+ static Json to_json(const basic_bigint<Allocator>& val)
1254
+ {
1255
+ std::basic_string<char_type> s;
1256
+ val.write_string(s);
1257
+ return Json(s,semantic_tag::bigint);
1258
+ }
1259
+ };
1260
+
1261
+ // std::valarray
1262
+
1263
+ template<class Json, class T>
1264
+ struct json_type_traits<Json, std::valarray<T>>
1265
+ {
1266
+ using allocator_type = typename Json::allocator_type;
1267
+
1268
+ static bool is(const Json& j) noexcept
1269
+ {
1270
+ bool result = j.is_array();
1271
+ if (result)
1272
+ {
1273
+ for (auto e : j.array_range())
1274
+ {
1275
+ if (!e.template is<T>())
1276
+ {
1277
+ result = false;
1278
+ break;
1279
+ }
1280
+ }
1281
+ }
1282
+ return result;
1283
+ }
1284
+
1285
+ static std::valarray<T> as(const Json& j)
1286
+ {
1287
+ if (j.is_array())
1288
+ {
1289
+ std::valarray<T> v(j.size());
1290
+ for (std::size_t i = 0; i < j.size(); ++i)
1291
+ {
1292
+ v[i] = j[i].template as<T>();
1293
+ }
1294
+ return v;
1295
+ }
1296
+ else
1297
+ {
1298
+ JSONCONS_THROW(conv_error(conv_errc::not_array));
1299
+ }
1300
+ }
1301
+
1302
+ static Json to_json(const std::valarray<T>& val)
1303
+ {
1304
+ Json j(json_array_arg);
1305
+ auto first = std::begin(val);
1306
+ auto last = std::end(val);
1307
+ std::size_t size = std::distance(first,last);
1308
+ j.reserve(size);
1309
+ for (auto it = first; it != last; ++it)
1310
+ {
1311
+ j.push_back(*it);
1312
+ }
1313
+ return j;
1314
+ }
1315
+
1316
+ static Json to_json(const std::valarray<T>& val, const allocator_type& alloc)
1317
+ {
1318
+ Json j(json_array_arg, alloc);
1319
+ auto first = std::begin(val);
1320
+ auto last = std::end(val);
1321
+ std::size_t size = std::distance(first,last);
1322
+ j.reserve(size);
1323
+ for (auto it = first; it != last; ++it)
1324
+ {
1325
+ j.push_back(*it);
1326
+ }
1327
+ return j;
1328
+ }
1329
+ };
1330
+
1331
+ #if defined(JSONCONS_HAS_STD_VARIANT)
1332
+
1333
+ namespace variant_detail
1334
+ {
1335
+ template<int N, class Json, class Variant, class ... Args>
1336
+ typename std::enable_if<N == std::variant_size_v<Variant>, bool>::type
1337
+ is_variant(const Json& /*j*/)
1338
+ {
1339
+ return false;
1340
+ }
1341
+
1342
+ template<std::size_t N, class Json, class Variant, class T, class ... U>
1343
+ typename std::enable_if<N < std::variant_size_v<Variant>, bool>::type
1344
+ is_variant(const Json& j)
1345
+ {
1346
+ if (j.template is<T>())
1347
+ {
1348
+ return true;
1349
+ }
1350
+ else
1351
+ {
1352
+ return is_variant<N+1, Json, Variant, U...>(j);
1353
+ }
1354
+ }
1355
+
1356
+ template<int N, class Json, class Variant, class ... Args>
1357
+ typename std::enable_if<N == std::variant_size_v<Variant>, Variant>::type
1358
+ as_variant(const Json& /*j*/)
1359
+ {
1360
+ JSONCONS_THROW(conv_error(conv_errc::not_variant));
1361
+ }
1362
+
1363
+ template<std::size_t N, class Json, class Variant, class T, class ... U>
1364
+ typename std::enable_if<N < std::variant_size_v<Variant>, Variant>::type
1365
+ as_variant(const Json& j)
1366
+ {
1367
+ if (j.template is<T>())
1368
+ {
1369
+ Variant var(j.template as<T>());
1370
+ return var;
1371
+ }
1372
+ else
1373
+ {
1374
+ return as_variant<N+1, Json, Variant, U...>(j);
1375
+ }
1376
+ }
1377
+
1378
+ template <class Json>
1379
+ struct variant_to_json_visitor
1380
+ {
1381
+ Json& j_;
1382
+
1383
+ variant_to_json_visitor(Json& j) : j_(j) {}
1384
+
1385
+ template<class T>
1386
+ void operator()(const T& value) const
1387
+ {
1388
+ j_ = value;
1389
+ }
1390
+ };
1391
+
1392
+ } // namespace variant_detail
1393
+
1394
+ template<class Json, typename... VariantTypes>
1395
+ struct json_type_traits<Json, std::variant<VariantTypes...>>
1396
+ {
1397
+ public:
1398
+ using variant_type = typename std::variant<VariantTypes...>;
1399
+ using allocator_type = typename Json::allocator_type;
1400
+
1401
+ static bool is(const Json& j) noexcept
1402
+ {
1403
+ return variant_detail::is_variant<0,Json,variant_type, VariantTypes...>(j);
1404
+ }
1405
+
1406
+ static std::variant<VariantTypes...> as(const Json& j)
1407
+ {
1408
+ return variant_detail::as_variant<0,Json,variant_type, VariantTypes...>(j);
1409
+ }
1410
+
1411
+ static Json to_json(const std::variant<VariantTypes...>& var)
1412
+ {
1413
+ Json j(json_array_arg);
1414
+ variant_detail::variant_to_json_visitor<Json> visitor(j);
1415
+ std::visit(visitor, var);
1416
+ return j;
1417
+ }
1418
+
1419
+ static Json to_json(const std::variant<VariantTypes...>& var,
1420
+ const allocator_type& alloc)
1421
+ {
1422
+ Json j(json_array_arg, alloc);
1423
+ variant_detail::variant_to_json_visitor<Json> visitor(j);
1424
+ std::visit(visitor, var);
1425
+ return j;
1426
+ }
1427
+ };
1428
+ #endif
1429
+
1430
+ // std::chrono::duration
1431
+ template<class Json,class Rep,class Period>
1432
+ struct json_type_traits<Json,std::chrono::duration<Rep,Period>>
1433
+ {
1434
+ using duration_type = std::chrono::duration<Rep,Period>;
1435
+
1436
+ using allocator_type = typename Json::allocator_type;
1437
+
1438
+ static constexpr int64_t nanos_in_milli = 1000000;
1439
+ static constexpr int64_t nanos_in_second = 1000000000;
1440
+ static constexpr int64_t millis_in_second = 1000;
1441
+
1442
+ static bool is(const Json& j) noexcept
1443
+ {
1444
+ return (j.tag() == semantic_tag::epoch_second || j.tag() == semantic_tag::epoch_milli || j.tag() == semantic_tag::epoch_nano);
1445
+ }
1446
+
1447
+ static duration_type as(const Json& j)
1448
+ {
1449
+ return from_json_(j);
1450
+ }
1451
+
1452
+ static Json to_json(const duration_type& val, allocator_type = allocator_type())
1453
+ {
1454
+ return to_json_(val);
1455
+ }
1456
+
1457
+ template <class PeriodT=Period>
1458
+ static
1459
+ typename std::enable_if<std::is_same<PeriodT,std::ratio<1>>::value, duration_type>::type
1460
+ from_json_(const Json& j)
1461
+ {
1462
+ if (j.is_int64() || j.is_uint64() || j.is_double())
1463
+ {
1464
+ auto count = j.template as<Rep>();
1465
+ switch (j.tag())
1466
+ {
1467
+ case semantic_tag::epoch_second:
1468
+ return duration_type(count);
1469
+ case semantic_tag::epoch_milli:
1470
+ return duration_type(count == 0 ? 0 : count/millis_in_second);
1471
+ case semantic_tag::epoch_nano:
1472
+ return duration_type(count == 0 ? 0 : count/nanos_in_second);
1473
+ default:
1474
+ return duration_type(count);
1475
+ }
1476
+ }
1477
+ else if (j.is_string())
1478
+ {
1479
+ switch (j.tag())
1480
+ {
1481
+ case semantic_tag::epoch_second:
1482
+ {
1483
+ auto count = j.template as<Rep>();
1484
+ return duration_type(count);
1485
+ }
1486
+ case semantic_tag::epoch_milli:
1487
+ {
1488
+ auto sv = j.as_string_view();
1489
+ bigint n = bigint::from_string(sv.data(), sv.length());
1490
+ if (n != 0)
1491
+ {
1492
+ n = n / millis_in_second;
1493
+ }
1494
+ return duration_type(static_cast<Rep>(n));
1495
+ }
1496
+ case semantic_tag::epoch_nano:
1497
+ {
1498
+ auto sv = j.as_string_view();
1499
+ bigint n = bigint::from_string(sv.data(), sv.length());
1500
+ if (n != 0)
1501
+ {
1502
+ n = n / nanos_in_second;
1503
+ }
1504
+ return duration_type(static_cast<Rep>(n));
1505
+ }
1506
+ default:
1507
+ {
1508
+ auto count = j.template as<Rep>();
1509
+ return duration_type(count);
1510
+ }
1511
+ }
1512
+ }
1513
+ else
1514
+ {
1515
+ return duration_type();
1516
+ }
1517
+ }
1518
+
1519
+ template <class PeriodT=Period>
1520
+ static
1521
+ typename std::enable_if<std::is_same<PeriodT,std::milli>::value, duration_type>::type
1522
+ from_json_(const Json& j)
1523
+ {
1524
+ if (j.is_int64() || j.is_uint64())
1525
+ {
1526
+ auto count = j.template as<Rep>();
1527
+ switch (j.tag())
1528
+ {
1529
+ case semantic_tag::epoch_second:
1530
+ return duration_type(count*millis_in_second);
1531
+ case semantic_tag::epoch_milli:
1532
+ return duration_type(count);
1533
+ case semantic_tag::epoch_nano:
1534
+ return duration_type(count == 0 ? 0 : count/nanos_in_milli);
1535
+ default:
1536
+ return duration_type(count);
1537
+ }
1538
+ }
1539
+ else if (j.is_double())
1540
+ {
1541
+ auto count = j.template as<double>();
1542
+ switch (j.tag())
1543
+ {
1544
+ case semantic_tag::epoch_second:
1545
+ return duration_type(static_cast<Rep>(count * millis_in_second));
1546
+ case semantic_tag::epoch_milli:
1547
+ return duration_type(static_cast<Rep>(count));
1548
+ case semantic_tag::epoch_nano:
1549
+ return duration_type(count == 0 ? 0 : static_cast<Rep>(count / nanos_in_milli));
1550
+ default:
1551
+ return duration_type(static_cast<Rep>(count));
1552
+ }
1553
+ }
1554
+ else if (j.is_string())
1555
+ {
1556
+ switch (j.tag())
1557
+ {
1558
+ case semantic_tag::epoch_second:
1559
+ {
1560
+ auto count = j.template as<Rep>();
1561
+ return duration_type(count*millis_in_second);
1562
+ }
1563
+ case semantic_tag::epoch_milli:
1564
+ {
1565
+ auto sv = j.as_string_view();
1566
+ Rep n{0};
1567
+ auto result = jsoncons::detail::to_integer_decimal(sv.data(), sv.size(), n);
1568
+ if (!result)
1569
+ {
1570
+ return duration_type();
1571
+ }
1572
+ return duration_type(n);
1573
+ }
1574
+ case semantic_tag::epoch_nano:
1575
+ {
1576
+ auto sv = j.as_string_view();
1577
+ bigint n = bigint::from_string(sv.data(), sv.length());
1578
+ if (n != 0)
1579
+ {
1580
+ n = n / nanos_in_milli;
1581
+ }
1582
+ return duration_type(static_cast<Rep>(n));
1583
+ }
1584
+ default:
1585
+ {
1586
+ auto count = j.template as<Rep>();
1587
+ return duration_type(count);
1588
+ }
1589
+ }
1590
+ }
1591
+ else
1592
+ {
1593
+ return duration_type();
1594
+ }
1595
+ }
1596
+
1597
+ template <class PeriodT=Period>
1598
+ static
1599
+ typename std::enable_if<std::is_same<PeriodT,std::nano>::value, duration_type>::type
1600
+ from_json_(const Json& j)
1601
+ {
1602
+ if (j.is_int64() || j.is_uint64() || j.is_double())
1603
+ {
1604
+ auto count = j.template as<Rep>();
1605
+ switch (j.tag())
1606
+ {
1607
+ case semantic_tag::epoch_second:
1608
+ return duration_type(count*nanos_in_second);
1609
+ case semantic_tag::epoch_milli:
1610
+ return duration_type(count*nanos_in_milli);
1611
+ case semantic_tag::epoch_nano:
1612
+ return duration_type(count);
1613
+ default:
1614
+ return duration_type(count);
1615
+ }
1616
+ }
1617
+ else if (j.is_double())
1618
+ {
1619
+ auto count = j.template as<double>();
1620
+ switch (j.tag())
1621
+ {
1622
+ case semantic_tag::epoch_second:
1623
+ return duration_type(static_cast<Rep>(count * nanos_in_second));
1624
+ case semantic_tag::epoch_milli:
1625
+ return duration_type(static_cast<Rep>(count * nanos_in_milli));
1626
+ case semantic_tag::epoch_nano:
1627
+ return duration_type(static_cast<Rep>(count));
1628
+ default:
1629
+ return duration_type(static_cast<Rep>(count));
1630
+ }
1631
+ }
1632
+ else if (j.is_string())
1633
+ {
1634
+ auto count = j.template as<Rep>();
1635
+ switch (j.tag())
1636
+ {
1637
+ case semantic_tag::epoch_second:
1638
+ return duration_type(count*nanos_in_second);
1639
+ case semantic_tag::epoch_milli:
1640
+ return duration_type(count*nanos_in_milli);
1641
+ case semantic_tag::epoch_nano:
1642
+ return duration_type(count);
1643
+ default:
1644
+ return duration_type(count);
1645
+ }
1646
+ }
1647
+ else
1648
+ {
1649
+ return duration_type();
1650
+ }
1651
+ }
1652
+
1653
+ template <class PeriodT=Period>
1654
+ static
1655
+ typename std::enable_if<std::is_same<PeriodT,std::ratio<1>>::value,Json>::type
1656
+ to_json_(const duration_type& val)
1657
+ {
1658
+ return Json(val.count(), semantic_tag::epoch_second);
1659
+ }
1660
+
1661
+ template <class PeriodT=Period>
1662
+ static
1663
+ typename std::enable_if<std::is_same<PeriodT,std::milli>::value,Json>::type
1664
+ to_json_(const duration_type& val)
1665
+ {
1666
+ return Json(val.count(), semantic_tag::epoch_milli);
1667
+ }
1668
+
1669
+ template <class PeriodT=Period>
1670
+ static
1671
+ typename std::enable_if<std::is_same<PeriodT,std::nano>::value,Json>::type
1672
+ to_json_(const duration_type& val)
1673
+ {
1674
+ return Json(val.count(), semantic_tag::epoch_nano);
1675
+ }
1676
+ };
1677
+
1678
+ // std::nullptr_t
1679
+ template <class Json>
1680
+ struct json_type_traits<Json,std::nullptr_t>
1681
+ {
1682
+ using allocator_type = typename Json::allocator_type;
1683
+
1684
+ static bool is(const Json& j) noexcept
1685
+ {
1686
+ return j.is_null();
1687
+ }
1688
+
1689
+ static std::nullptr_t as(const Json& j)
1690
+ {
1691
+ if (!j.is_null())
1692
+ {
1693
+ JSONCONS_THROW(conv_error(conv_errc::not_nullptr));
1694
+ }
1695
+ return nullptr;
1696
+ }
1697
+
1698
+ static Json to_json(const std::nullptr_t&, allocator_type = allocator_type())
1699
+ {
1700
+ return Json::null();
1701
+ }
1702
+ };
1703
+
1704
+ // std::bitset
1705
+
1706
+ struct null_back_insertable_byte_container
1707
+ {
1708
+ using value_type = uint8_t;
1709
+
1710
+ void push_back(value_type)
1711
+ {
1712
+ }
1713
+ };
1714
+
1715
+ template<class Json, std::size_t N>
1716
+ struct json_type_traits<Json, std::bitset<N>>
1717
+ {
1718
+ using allocator_type = typename Json::allocator_type;
1719
+
1720
+ static bool is(const Json& j) noexcept
1721
+ {
1722
+ if (j.is_byte_string())
1723
+ {
1724
+ return true;
1725
+ }
1726
+ else if (j.is_string())
1727
+ {
1728
+ jsoncons::string_view sv = j.as_string_view();
1729
+ null_back_insertable_byte_container cont;
1730
+ auto result = decode_base16(sv.begin(), sv.end(), cont);
1731
+ return result.ec == conv_errc::success ? true : false;
1732
+ }
1733
+ return false;
1734
+ }
1735
+
1736
+ static std::bitset<N> as(const Json& j)
1737
+ {
1738
+ if (j.template is<uint64_t>())
1739
+ {
1740
+ auto bits = j.template as<uint64_t>();
1741
+ std::bitset<N> bs = static_cast<unsigned long long>(bits);
1742
+ return bs;
1743
+ }
1744
+ else if (j.is_byte_string() || j.is_string())
1745
+ {
1746
+ std::bitset<N> bs;
1747
+ std::vector<uint8_t> bits;
1748
+ if (j.is_byte_string())
1749
+ {
1750
+ bits = j.template as<std::vector<uint8_t>>();
1751
+ }
1752
+ else
1753
+ {
1754
+ jsoncons::string_view sv = j.as_string_view();
1755
+ auto result = decode_base16(sv.begin(), sv.end(), bits);
1756
+ if (result.ec != conv_errc::success)
1757
+ {
1758
+ JSONCONS_THROW(conv_error(conv_errc::not_bitset));
1759
+ }
1760
+ }
1761
+ std::uint8_t byte = 0;
1762
+ std::uint8_t mask = 0;
1763
+
1764
+ std::size_t pos = 0;
1765
+ for (std::size_t i = 0; i < N; ++i)
1766
+ {
1767
+ if (mask == 0)
1768
+ {
1769
+ if (pos >= bits.size())
1770
+ {
1771
+ JSONCONS_THROW(conv_error(conv_errc::not_bitset));
1772
+ }
1773
+ byte = bits.at(pos++);
1774
+ mask = 0x80;
1775
+ }
1776
+
1777
+ if (byte & mask)
1778
+ {
1779
+ bs[i] = 1;
1780
+ }
1781
+
1782
+ mask = static_cast<std::uint8_t>(mask >> 1);
1783
+ }
1784
+ return bs;
1785
+ }
1786
+ else
1787
+ {
1788
+ JSONCONS_THROW(conv_error(conv_errc::not_bitset));
1789
+ }
1790
+ }
1791
+
1792
+ static Json to_json(const std::bitset<N>& val,
1793
+ const allocator_type& alloc = allocator_type())
1794
+ {
1795
+ std::vector<uint8_t> bits;
1796
+
1797
+ uint8_t byte = 0;
1798
+ uint8_t mask = 0x80;
1799
+
1800
+ for (std::size_t i = 0; i < N; ++i)
1801
+ {
1802
+ if (val[i])
1803
+ {
1804
+ byte |= mask;
1805
+ }
1806
+
1807
+ mask = static_cast<uint8_t>(mask >> 1);
1808
+
1809
+ if (mask == 0)
1810
+ {
1811
+ bits.push_back(byte);
1812
+ byte = 0;
1813
+ mask = 0x80;
1814
+ }
1815
+ }
1816
+
1817
+ // Encode remainder
1818
+ if (mask != 0x80)
1819
+ {
1820
+ bits.push_back(byte);
1821
+ }
1822
+
1823
+ Json j(byte_string_arg, bits, semantic_tag::base16, alloc);
1824
+ return j;
1825
+ }
1826
+ };
1827
+
1828
+ } // jsoncons
1829
+
1830
+ #endif