jsoncons 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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