Mercurial > minori
comparison dep/json/json.hpp @ 175:9b10175be389
dep/json: update to v3.11.3
anime/db: save anime list to database, very much untested and likely won't work as intended
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Thu, 30 Nov 2023 13:52:26 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
174:f88eda79c60a | 175:9b10175be389 |
---|---|
1 // __ _____ _____ _____ | |
2 // __| | __| | | | JSON for Modern C++ | |
3 // | | |__ | | | | | | version 3.11.3 | |
4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
5 // | |
6 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
7 // SPDX-License-Identifier: MIT | |
8 | |
9 /****************************************************************************\ | |
10 * Note on documentation: The source files contain links to the online * | |
11 * documentation of the public API at https://json.nlohmann.me. This URL * | |
12 * contains the most recent documentation and should also be applicable to * | |
13 * previous versions; documentation for deprecated functions is not * | |
14 * removed, but marked deprecated. See "Generate documentation" section in * | |
15 * file docs/README.md. * | |
16 \****************************************************************************/ | |
17 | |
18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_ | |
19 #define INCLUDE_NLOHMANN_JSON_HPP_ | |
20 | |
21 #include <algorithm> // all_of, find, for_each | |
22 #include <cstddef> // nullptr_t, ptrdiff_t, size_t | |
23 #include <functional> // hash, less | |
24 #include <initializer_list> // initializer_list | |
25 #ifndef JSON_NO_IO | |
26 #include <iosfwd> // istream, ostream | |
27 #endif // JSON_NO_IO | |
28 #include <iterator> // random_access_iterator_tag | |
29 #include <memory> // unique_ptr | |
30 #include <string> // string, stoi, to_string | |
31 #include <utility> // declval, forward, move, pair, swap | |
32 #include <vector> // vector | |
33 | |
34 // #include <nlohmann/adl_serializer.hpp> | |
35 // __ _____ _____ _____ | |
36 // __| | __| | | | JSON for Modern C++ | |
37 // | | |__ | | | | | | version 3.11.3 | |
38 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
39 // | |
40 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
41 // SPDX-License-Identifier: MIT | |
42 | |
43 | |
44 | |
45 #include <utility> | |
46 | |
47 // #include <nlohmann/detail/abi_macros.hpp> | |
48 // __ _____ _____ _____ | |
49 // __| | __| | | | JSON for Modern C++ | |
50 // | | |__ | | | | | | version 3.11.3 | |
51 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
52 // | |
53 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
54 // SPDX-License-Identifier: MIT | |
55 | |
56 | |
57 | |
58 // This file contains all macro definitions affecting or depending on the ABI | |
59 | |
60 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK | |
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) | |
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 | |
63 #warning "Already included a different version of the library!" | |
64 #endif | |
65 #endif | |
66 #endif | |
67 | |
68 #define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) | |
69 #define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) | |
70 #define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) | |
71 | |
72 #ifndef JSON_DIAGNOSTICS | |
73 #define JSON_DIAGNOSTICS 0 | |
74 #endif | |
75 | |
76 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | |
77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 | |
78 #endif | |
79 | |
80 #if JSON_DIAGNOSTICS | |
81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag | |
82 #else | |
83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS | |
84 #endif | |
85 | |
86 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | |
87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp | |
88 #else | |
89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON | |
90 #endif | |
91 | |
92 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION | |
93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 | |
94 #endif | |
95 | |
96 // Construct the namespace ABI tags component | |
97 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b | |
98 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ | |
99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) | |
100 | |
101 #define NLOHMANN_JSON_ABI_TAGS \ | |
102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \ | |
103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ | |
104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) | |
105 | |
106 // Construct the namespace version component | |
107 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ | |
108 _v ## major ## _ ## minor ## _ ## patch | |
109 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ | |
110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) | |
111 | |
112 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION | |
113 #define NLOHMANN_JSON_NAMESPACE_VERSION | |
114 #else | |
115 #define NLOHMANN_JSON_NAMESPACE_VERSION \ | |
116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ | |
117 NLOHMANN_JSON_VERSION_MINOR, \ | |
118 NLOHMANN_JSON_VERSION_PATCH) | |
119 #endif | |
120 | |
121 // Combine namespace components | |
122 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b | |
123 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ | |
124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) | |
125 | |
126 #ifndef NLOHMANN_JSON_NAMESPACE | |
127 #define NLOHMANN_JSON_NAMESPACE \ | |
128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ | |
129 NLOHMANN_JSON_ABI_TAGS, \ | |
130 NLOHMANN_JSON_NAMESPACE_VERSION) | |
131 #endif | |
132 | |
133 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN | |
134 #define NLOHMANN_JSON_NAMESPACE_BEGIN \ | |
135 namespace nlohmann \ | |
136 { \ | |
137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ | |
138 NLOHMANN_JSON_ABI_TAGS, \ | |
139 NLOHMANN_JSON_NAMESPACE_VERSION) \ | |
140 { | |
141 #endif | |
142 | |
143 #ifndef NLOHMANN_JSON_NAMESPACE_END | |
144 #define NLOHMANN_JSON_NAMESPACE_END \ | |
145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ | |
146 } // namespace nlohmann | |
147 #endif | |
148 | |
149 // #include <nlohmann/detail/conversions/from_json.hpp> | |
150 // __ _____ _____ _____ | |
151 // __| | __| | | | JSON for Modern C++ | |
152 // | | |__ | | | | | | version 3.11.3 | |
153 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
154 // | |
155 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
156 // SPDX-License-Identifier: MIT | |
157 | |
158 | |
159 | |
160 #include <algorithm> // transform | |
161 #include <array> // array | |
162 #include <forward_list> // forward_list | |
163 #include <iterator> // inserter, front_inserter, end | |
164 #include <map> // map | |
165 #include <string> // string | |
166 #include <tuple> // tuple, make_tuple | |
167 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible | |
168 #include <unordered_map> // unordered_map | |
169 #include <utility> // pair, declval | |
170 #include <valarray> // valarray | |
171 | |
172 // #include <nlohmann/detail/exceptions.hpp> | |
173 // __ _____ _____ _____ | |
174 // __| | __| | | | JSON for Modern C++ | |
175 // | | |__ | | | | | | version 3.11.3 | |
176 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
177 // | |
178 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
179 // SPDX-License-Identifier: MIT | |
180 | |
181 | |
182 | |
183 #include <cstddef> // nullptr_t | |
184 #include <exception> // exception | |
185 #if JSON_DIAGNOSTICS | |
186 #include <numeric> // accumulate | |
187 #endif | |
188 #include <stdexcept> // runtime_error | |
189 #include <string> // to_string | |
190 #include <vector> // vector | |
191 | |
192 // #include <nlohmann/detail/value_t.hpp> | |
193 // __ _____ _____ _____ | |
194 // __| | __| | | | JSON for Modern C++ | |
195 // | | |__ | | | | | | version 3.11.3 | |
196 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
197 // | |
198 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
199 // SPDX-License-Identifier: MIT | |
200 | |
201 | |
202 | |
203 #include <array> // array | |
204 #include <cstddef> // size_t | |
205 #include <cstdint> // uint8_t | |
206 #include <string> // string | |
207 | |
208 // #include <nlohmann/detail/macro_scope.hpp> | |
209 // __ _____ _____ _____ | |
210 // __| | __| | | | JSON for Modern C++ | |
211 // | | |__ | | | | | | version 3.11.3 | |
212 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
213 // | |
214 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
215 // SPDX-License-Identifier: MIT | |
216 | |
217 | |
218 | |
219 #include <utility> // declval, pair | |
220 // #include <nlohmann/detail/meta/detected.hpp> | |
221 // __ _____ _____ _____ | |
222 // __| | __| | | | JSON for Modern C++ | |
223 // | | |__ | | | | | | version 3.11.3 | |
224 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
225 // | |
226 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
227 // SPDX-License-Identifier: MIT | |
228 | |
229 | |
230 | |
231 #include <type_traits> | |
232 | |
233 // #include <nlohmann/detail/meta/void_t.hpp> | |
234 // __ _____ _____ _____ | |
235 // __| | __| | | | JSON for Modern C++ | |
236 // | | |__ | | | | | | version 3.11.3 | |
237 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
238 // | |
239 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
240 // SPDX-License-Identifier: MIT | |
241 | |
242 | |
243 | |
244 // #include <nlohmann/detail/abi_macros.hpp> | |
245 | |
246 | |
247 NLOHMANN_JSON_NAMESPACE_BEGIN | |
248 namespace detail | |
249 { | |
250 | |
251 template<typename ...Ts> struct make_void | |
252 { | |
253 using type = void; | |
254 }; | |
255 template<typename ...Ts> using void_t = typename make_void<Ts...>::type; | |
256 | |
257 } // namespace detail | |
258 NLOHMANN_JSON_NAMESPACE_END | |
259 | |
260 | |
261 NLOHMANN_JSON_NAMESPACE_BEGIN | |
262 namespace detail | |
263 { | |
264 | |
265 // https://en.cppreference.com/w/cpp/experimental/is_detected | |
266 struct nonesuch | |
267 { | |
268 nonesuch() = delete; | |
269 ~nonesuch() = delete; | |
270 nonesuch(nonesuch const&) = delete; | |
271 nonesuch(nonesuch const&&) = delete; | |
272 void operator=(nonesuch const&) = delete; | |
273 void operator=(nonesuch&&) = delete; | |
274 }; | |
275 | |
276 template<class Default, | |
277 class AlwaysVoid, | |
278 template<class...> class Op, | |
279 class... Args> | |
280 struct detector | |
281 { | |
282 using value_t = std::false_type; | |
283 using type = Default; | |
284 }; | |
285 | |
286 template<class Default, template<class...> class Op, class... Args> | |
287 struct detector<Default, void_t<Op<Args...>>, Op, Args...> | |
288 { | |
289 using value_t = std::true_type; | |
290 using type = Op<Args...>; | |
291 }; | |
292 | |
293 template<template<class...> class Op, class... Args> | |
294 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; | |
295 | |
296 template<template<class...> class Op, class... Args> | |
297 struct is_detected_lazy : is_detected<Op, Args...> { }; | |
298 | |
299 template<template<class...> class Op, class... Args> | |
300 using detected_t = typename detector<nonesuch, void, Op, Args...>::type; | |
301 | |
302 template<class Default, template<class...> class Op, class... Args> | |
303 using detected_or = detector<Default, void, Op, Args...>; | |
304 | |
305 template<class Default, template<class...> class Op, class... Args> | |
306 using detected_or_t = typename detected_or<Default, Op, Args...>::type; | |
307 | |
308 template<class Expected, template<class...> class Op, class... Args> | |
309 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; | |
310 | |
311 template<class To, template<class...> class Op, class... Args> | |
312 using is_detected_convertible = | |
313 std::is_convertible<detected_t<Op, Args...>, To>; | |
314 | |
315 } // namespace detail | |
316 NLOHMANN_JSON_NAMESPACE_END | |
317 | |
318 // #include <nlohmann/thirdparty/hedley/hedley.hpp> | |
319 | |
320 | |
321 // __ _____ _____ _____ | |
322 // __| | __| | | | JSON for Modern C++ | |
323 // | | |__ | | | | | | version 3.11.3 | |
324 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
325 // | |
326 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
327 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com> | |
328 // SPDX-License-Identifier: MIT | |
329 | |
330 /* Hedley - https://nemequ.github.io/hedley | |
331 * Created by Evan Nemerson <evan@nemerson.com> | |
332 */ | |
333 | |
334 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) | |
335 #if defined(JSON_HEDLEY_VERSION) | |
336 #undef JSON_HEDLEY_VERSION | |
337 #endif | |
338 #define JSON_HEDLEY_VERSION 15 | |
339 | |
340 #if defined(JSON_HEDLEY_STRINGIFY_EX) | |
341 #undef JSON_HEDLEY_STRINGIFY_EX | |
342 #endif | |
343 #define JSON_HEDLEY_STRINGIFY_EX(x) #x | |
344 | |
345 #if defined(JSON_HEDLEY_STRINGIFY) | |
346 #undef JSON_HEDLEY_STRINGIFY | |
347 #endif | |
348 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) | |
349 | |
350 #if defined(JSON_HEDLEY_CONCAT_EX) | |
351 #undef JSON_HEDLEY_CONCAT_EX | |
352 #endif | |
353 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b | |
354 | |
355 #if defined(JSON_HEDLEY_CONCAT) | |
356 #undef JSON_HEDLEY_CONCAT | |
357 #endif | |
358 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) | |
359 | |
360 #if defined(JSON_HEDLEY_CONCAT3_EX) | |
361 #undef JSON_HEDLEY_CONCAT3_EX | |
362 #endif | |
363 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c | |
364 | |
365 #if defined(JSON_HEDLEY_CONCAT3) | |
366 #undef JSON_HEDLEY_CONCAT3 | |
367 #endif | |
368 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) | |
369 | |
370 #if defined(JSON_HEDLEY_VERSION_ENCODE) | |
371 #undef JSON_HEDLEY_VERSION_ENCODE | |
372 #endif | |
373 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) | |
374 | |
375 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) | |
376 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR | |
377 #endif | |
378 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) | |
379 | |
380 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) | |
381 #undef JSON_HEDLEY_VERSION_DECODE_MINOR | |
382 #endif | |
383 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) | |
384 | |
385 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) | |
386 #undef JSON_HEDLEY_VERSION_DECODE_REVISION | |
387 #endif | |
388 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) | |
389 | |
390 #if defined(JSON_HEDLEY_GNUC_VERSION) | |
391 #undef JSON_HEDLEY_GNUC_VERSION | |
392 #endif | |
393 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) | |
394 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) | |
395 #elif defined(__GNUC__) | |
396 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) | |
397 #endif | |
398 | |
399 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) | |
400 #undef JSON_HEDLEY_GNUC_VERSION_CHECK | |
401 #endif | |
402 #if defined(JSON_HEDLEY_GNUC_VERSION) | |
403 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
404 #else | |
405 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) | |
406 #endif | |
407 | |
408 #if defined(JSON_HEDLEY_MSVC_VERSION) | |
409 #undef JSON_HEDLEY_MSVC_VERSION | |
410 #endif | |
411 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) | |
412 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) | |
413 #elif defined(_MSC_FULL_VER) && !defined(__ICL) | |
414 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) | |
415 #elif defined(_MSC_VER) && !defined(__ICL) | |
416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) | |
417 #endif | |
418 | |
419 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) | |
420 #undef JSON_HEDLEY_MSVC_VERSION_CHECK | |
421 #endif | |
422 #if !defined(JSON_HEDLEY_MSVC_VERSION) | |
423 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) | |
424 #elif defined(_MSC_VER) && (_MSC_VER >= 1400) | |
425 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) | |
426 #elif defined(_MSC_VER) && (_MSC_VER >= 1200) | |
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) | |
428 #else | |
429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) | |
430 #endif | |
431 | |
432 #if defined(JSON_HEDLEY_INTEL_VERSION) | |
433 #undef JSON_HEDLEY_INTEL_VERSION | |
434 #endif | |
435 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) | |
436 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) | |
437 #elif defined(__INTEL_COMPILER) && !defined(__ICL) | |
438 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) | |
439 #endif | |
440 | |
441 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) | |
442 #undef JSON_HEDLEY_INTEL_VERSION_CHECK | |
443 #endif | |
444 #if defined(JSON_HEDLEY_INTEL_VERSION) | |
445 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
446 #else | |
447 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) | |
448 #endif | |
449 | |
450 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) | |
451 #undef JSON_HEDLEY_INTEL_CL_VERSION | |
452 #endif | |
453 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) | |
454 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) | |
455 #endif | |
456 | |
457 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) | |
458 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK | |
459 #endif | |
460 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) | |
461 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
462 #else | |
463 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) | |
464 #endif | |
465 | |
466 #if defined(JSON_HEDLEY_PGI_VERSION) | |
467 #undef JSON_HEDLEY_PGI_VERSION | |
468 #endif | |
469 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) | |
470 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) | |
471 #endif | |
472 | |
473 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK) | |
474 #undef JSON_HEDLEY_PGI_VERSION_CHECK | |
475 #endif | |
476 #if defined(JSON_HEDLEY_PGI_VERSION) | |
477 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
478 #else | |
479 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) | |
480 #endif | |
481 | |
482 #if defined(JSON_HEDLEY_SUNPRO_VERSION) | |
483 #undef JSON_HEDLEY_SUNPRO_VERSION | |
484 #endif | |
485 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) | |
486 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) | |
487 #elif defined(__SUNPRO_C) | |
488 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) | |
489 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) | |
490 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) | |
491 #elif defined(__SUNPRO_CC) | |
492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) | |
493 #endif | |
494 | |
495 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) | |
496 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK | |
497 #endif | |
498 #if defined(JSON_HEDLEY_SUNPRO_VERSION) | |
499 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
500 #else | |
501 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) | |
502 #endif | |
503 | |
504 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) | |
505 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION | |
506 #endif | |
507 #if defined(__EMSCRIPTEN__) | |
508 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) | |
509 #endif | |
510 | |
511 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) | |
512 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK | |
513 #endif | |
514 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) | |
515 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
516 #else | |
517 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) | |
518 #endif | |
519 | |
520 #if defined(JSON_HEDLEY_ARM_VERSION) | |
521 #undef JSON_HEDLEY_ARM_VERSION | |
522 #endif | |
523 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) | |
524 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) | |
525 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) | |
526 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) | |
527 #endif | |
528 | |
529 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK) | |
530 #undef JSON_HEDLEY_ARM_VERSION_CHECK | |
531 #endif | |
532 #if defined(JSON_HEDLEY_ARM_VERSION) | |
533 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
534 #else | |
535 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) | |
536 #endif | |
537 | |
538 #if defined(JSON_HEDLEY_IBM_VERSION) | |
539 #undef JSON_HEDLEY_IBM_VERSION | |
540 #endif | |
541 #if defined(__ibmxl__) | |
542 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) | |
543 #elif defined(__xlC__) && defined(__xlC_ver__) | |
544 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) | |
545 #elif defined(__xlC__) | |
546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) | |
547 #endif | |
548 | |
549 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK) | |
550 #undef JSON_HEDLEY_IBM_VERSION_CHECK | |
551 #endif | |
552 #if defined(JSON_HEDLEY_IBM_VERSION) | |
553 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
554 #else | |
555 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) | |
556 #endif | |
557 | |
558 #if defined(JSON_HEDLEY_TI_VERSION) | |
559 #undef JSON_HEDLEY_TI_VERSION | |
560 #endif | |
561 #if \ | |
562 defined(__TI_COMPILER_VERSION__) && \ | |
563 ( \ | |
564 defined(__TMS470__) || defined(__TI_ARM__) || \ | |
565 defined(__MSP430__) || \ | |
566 defined(__TMS320C2000__) \ | |
567 ) | |
568 #if (__TI_COMPILER_VERSION__ >= 16000000) | |
569 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
570 #endif | |
571 #endif | |
572 | |
573 #if defined(JSON_HEDLEY_TI_VERSION_CHECK) | |
574 #undef JSON_HEDLEY_TI_VERSION_CHECK | |
575 #endif | |
576 #if defined(JSON_HEDLEY_TI_VERSION) | |
577 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
578 #else | |
579 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) | |
580 #endif | |
581 | |
582 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) | |
583 #undef JSON_HEDLEY_TI_CL2000_VERSION | |
584 #endif | |
585 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) | |
586 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
587 #endif | |
588 | |
589 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) | |
590 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK | |
591 #endif | |
592 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) | |
593 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
594 #else | |
595 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) | |
596 #endif | |
597 | |
598 #if defined(JSON_HEDLEY_TI_CL430_VERSION) | |
599 #undef JSON_HEDLEY_TI_CL430_VERSION | |
600 #endif | |
601 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) | |
602 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
603 #endif | |
604 | |
605 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) | |
606 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK | |
607 #endif | |
608 #if defined(JSON_HEDLEY_TI_CL430_VERSION) | |
609 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
610 #else | |
611 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) | |
612 #endif | |
613 | |
614 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) | |
615 #undef JSON_HEDLEY_TI_ARMCL_VERSION | |
616 #endif | |
617 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) | |
618 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
619 #endif | |
620 | |
621 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) | |
622 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK | |
623 #endif | |
624 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) | |
625 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
626 #else | |
627 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) | |
628 #endif | |
629 | |
630 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) | |
631 #undef JSON_HEDLEY_TI_CL6X_VERSION | |
632 #endif | |
633 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) | |
634 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
635 #endif | |
636 | |
637 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) | |
638 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK | |
639 #endif | |
640 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) | |
641 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
642 #else | |
643 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) | |
644 #endif | |
645 | |
646 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) | |
647 #undef JSON_HEDLEY_TI_CL7X_VERSION | |
648 #endif | |
649 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) | |
650 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
651 #endif | |
652 | |
653 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) | |
654 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK | |
655 #endif | |
656 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) | |
657 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
658 #else | |
659 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) | |
660 #endif | |
661 | |
662 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) | |
663 #undef JSON_HEDLEY_TI_CLPRU_VERSION | |
664 #endif | |
665 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) | |
666 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) | |
667 #endif | |
668 | |
669 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) | |
670 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK | |
671 #endif | |
672 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) | |
673 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
674 #else | |
675 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) | |
676 #endif | |
677 | |
678 #if defined(JSON_HEDLEY_CRAY_VERSION) | |
679 #undef JSON_HEDLEY_CRAY_VERSION | |
680 #endif | |
681 #if defined(_CRAYC) | |
682 #if defined(_RELEASE_PATCHLEVEL) | |
683 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) | |
684 #else | |
685 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) | |
686 #endif | |
687 #endif | |
688 | |
689 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) | |
690 #undef JSON_HEDLEY_CRAY_VERSION_CHECK | |
691 #endif | |
692 #if defined(JSON_HEDLEY_CRAY_VERSION) | |
693 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
694 #else | |
695 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) | |
696 #endif | |
697 | |
698 #if defined(JSON_HEDLEY_IAR_VERSION) | |
699 #undef JSON_HEDLEY_IAR_VERSION | |
700 #endif | |
701 #if defined(__IAR_SYSTEMS_ICC__) | |
702 #if __VER__ > 1000 | |
703 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) | |
704 #else | |
705 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) | |
706 #endif | |
707 #endif | |
708 | |
709 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK) | |
710 #undef JSON_HEDLEY_IAR_VERSION_CHECK | |
711 #endif | |
712 #if defined(JSON_HEDLEY_IAR_VERSION) | |
713 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
714 #else | |
715 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) | |
716 #endif | |
717 | |
718 #if defined(JSON_HEDLEY_TINYC_VERSION) | |
719 #undef JSON_HEDLEY_TINYC_VERSION | |
720 #endif | |
721 #if defined(__TINYC__) | |
722 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) | |
723 #endif | |
724 | |
725 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) | |
726 #undef JSON_HEDLEY_TINYC_VERSION_CHECK | |
727 #endif | |
728 #if defined(JSON_HEDLEY_TINYC_VERSION) | |
729 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
730 #else | |
731 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) | |
732 #endif | |
733 | |
734 #if defined(JSON_HEDLEY_DMC_VERSION) | |
735 #undef JSON_HEDLEY_DMC_VERSION | |
736 #endif | |
737 #if defined(__DMC__) | |
738 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) | |
739 #endif | |
740 | |
741 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK) | |
742 #undef JSON_HEDLEY_DMC_VERSION_CHECK | |
743 #endif | |
744 #if defined(JSON_HEDLEY_DMC_VERSION) | |
745 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
746 #else | |
747 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) | |
748 #endif | |
749 | |
750 #if defined(JSON_HEDLEY_COMPCERT_VERSION) | |
751 #undef JSON_HEDLEY_COMPCERT_VERSION | |
752 #endif | |
753 #if defined(__COMPCERT_VERSION__) | |
754 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) | |
755 #endif | |
756 | |
757 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) | |
758 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK | |
759 #endif | |
760 #if defined(JSON_HEDLEY_COMPCERT_VERSION) | |
761 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
762 #else | |
763 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) | |
764 #endif | |
765 | |
766 #if defined(JSON_HEDLEY_PELLES_VERSION) | |
767 #undef JSON_HEDLEY_PELLES_VERSION | |
768 #endif | |
769 #if defined(__POCC__) | |
770 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) | |
771 #endif | |
772 | |
773 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) | |
774 #undef JSON_HEDLEY_PELLES_VERSION_CHECK | |
775 #endif | |
776 #if defined(JSON_HEDLEY_PELLES_VERSION) | |
777 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
778 #else | |
779 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) | |
780 #endif | |
781 | |
782 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) | |
783 #undef JSON_HEDLEY_MCST_LCC_VERSION | |
784 #endif | |
785 #if defined(__LCC__) && defined(__LCC_MINOR__) | |
786 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) | |
787 #endif | |
788 | |
789 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) | |
790 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK | |
791 #endif | |
792 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) | |
793 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
794 #else | |
795 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) | |
796 #endif | |
797 | |
798 #if defined(JSON_HEDLEY_GCC_VERSION) | |
799 #undef JSON_HEDLEY_GCC_VERSION | |
800 #endif | |
801 #if \ | |
802 defined(JSON_HEDLEY_GNUC_VERSION) && \ | |
803 !defined(__clang__) && \ | |
804 !defined(JSON_HEDLEY_INTEL_VERSION) && \ | |
805 !defined(JSON_HEDLEY_PGI_VERSION) && \ | |
806 !defined(JSON_HEDLEY_ARM_VERSION) && \ | |
807 !defined(JSON_HEDLEY_CRAY_VERSION) && \ | |
808 !defined(JSON_HEDLEY_TI_VERSION) && \ | |
809 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ | |
810 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ | |
811 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ | |
812 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ | |
813 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ | |
814 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ | |
815 !defined(__COMPCERT__) && \ | |
816 !defined(JSON_HEDLEY_MCST_LCC_VERSION) | |
817 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION | |
818 #endif | |
819 | |
820 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK) | |
821 #undef JSON_HEDLEY_GCC_VERSION_CHECK | |
822 #endif | |
823 #if defined(JSON_HEDLEY_GCC_VERSION) | |
824 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) | |
825 #else | |
826 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) | |
827 #endif | |
828 | |
829 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) | |
830 #undef JSON_HEDLEY_HAS_ATTRIBUTE | |
831 #endif | |
832 #if \ | |
833 defined(__has_attribute) && \ | |
834 ( \ | |
835 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ | |
836 ) | |
837 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) | |
838 #else | |
839 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) | |
840 #endif | |
841 | |
842 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) | |
843 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE | |
844 #endif | |
845 #if defined(__has_attribute) | |
846 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) | |
847 #else | |
848 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
849 #endif | |
850 | |
851 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) | |
852 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE | |
853 #endif | |
854 #if defined(__has_attribute) | |
855 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) | |
856 #else | |
857 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
858 #endif | |
859 | |
860 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) | |
861 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE | |
862 #endif | |
863 #if \ | |
864 defined(__has_cpp_attribute) && \ | |
865 defined(__cplusplus) && \ | |
866 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) | |
867 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) | |
868 #else | |
869 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) | |
870 #endif | |
871 | |
872 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) | |
873 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS | |
874 #endif | |
875 #if !defined(__cplusplus) || !defined(__has_cpp_attribute) | |
876 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) | |
877 #elif \ | |
878 !defined(JSON_HEDLEY_PGI_VERSION) && \ | |
879 !defined(JSON_HEDLEY_IAR_VERSION) && \ | |
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ | |
881 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) | |
882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) | |
883 #else | |
884 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) | |
885 #endif | |
886 | |
887 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) | |
888 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE | |
889 #endif | |
890 #if defined(__has_cpp_attribute) && defined(__cplusplus) | |
891 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) | |
892 #else | |
893 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
894 #endif | |
895 | |
896 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) | |
897 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE | |
898 #endif | |
899 #if defined(__has_cpp_attribute) && defined(__cplusplus) | |
900 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) | |
901 #else | |
902 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
903 #endif | |
904 | |
905 #if defined(JSON_HEDLEY_HAS_BUILTIN) | |
906 #undef JSON_HEDLEY_HAS_BUILTIN | |
907 #endif | |
908 #if defined(__has_builtin) | |
909 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) | |
910 #else | |
911 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) | |
912 #endif | |
913 | |
914 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) | |
915 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN | |
916 #endif | |
917 #if defined(__has_builtin) | |
918 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) | |
919 #else | |
920 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
921 #endif | |
922 | |
923 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) | |
924 #undef JSON_HEDLEY_GCC_HAS_BUILTIN | |
925 #endif | |
926 #if defined(__has_builtin) | |
927 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) | |
928 #else | |
929 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
930 #endif | |
931 | |
932 #if defined(JSON_HEDLEY_HAS_FEATURE) | |
933 #undef JSON_HEDLEY_HAS_FEATURE | |
934 #endif | |
935 #if defined(__has_feature) | |
936 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) | |
937 #else | |
938 #define JSON_HEDLEY_HAS_FEATURE(feature) (0) | |
939 #endif | |
940 | |
941 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) | |
942 #undef JSON_HEDLEY_GNUC_HAS_FEATURE | |
943 #endif | |
944 #if defined(__has_feature) | |
945 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) | |
946 #else | |
947 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
948 #endif | |
949 | |
950 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE) | |
951 #undef JSON_HEDLEY_GCC_HAS_FEATURE | |
952 #endif | |
953 #if defined(__has_feature) | |
954 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) | |
955 #else | |
956 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
957 #endif | |
958 | |
959 #if defined(JSON_HEDLEY_HAS_EXTENSION) | |
960 #undef JSON_HEDLEY_HAS_EXTENSION | |
961 #endif | |
962 #if defined(__has_extension) | |
963 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) | |
964 #else | |
965 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) | |
966 #endif | |
967 | |
968 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) | |
969 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION | |
970 #endif | |
971 #if defined(__has_extension) | |
972 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) | |
973 #else | |
974 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
975 #endif | |
976 | |
977 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) | |
978 #undef JSON_HEDLEY_GCC_HAS_EXTENSION | |
979 #endif | |
980 #if defined(__has_extension) | |
981 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) | |
982 #else | |
983 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
984 #endif | |
985 | |
986 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) | |
987 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE | |
988 #endif | |
989 #if defined(__has_declspec_attribute) | |
990 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) | |
991 #else | |
992 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) | |
993 #endif | |
994 | |
995 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) | |
996 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE | |
997 #endif | |
998 #if defined(__has_declspec_attribute) | |
999 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) | |
1000 #else | |
1001 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
1002 #endif | |
1003 | |
1004 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) | |
1005 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE | |
1006 #endif | |
1007 #if defined(__has_declspec_attribute) | |
1008 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) | |
1009 #else | |
1010 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
1011 #endif | |
1012 | |
1013 #if defined(JSON_HEDLEY_HAS_WARNING) | |
1014 #undef JSON_HEDLEY_HAS_WARNING | |
1015 #endif | |
1016 #if defined(__has_warning) | |
1017 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) | |
1018 #else | |
1019 #define JSON_HEDLEY_HAS_WARNING(warning) (0) | |
1020 #endif | |
1021 | |
1022 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING) | |
1023 #undef JSON_HEDLEY_GNUC_HAS_WARNING | |
1024 #endif | |
1025 #if defined(__has_warning) | |
1026 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) | |
1027 #else | |
1028 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) | |
1029 #endif | |
1030 | |
1031 #if defined(JSON_HEDLEY_GCC_HAS_WARNING) | |
1032 #undef JSON_HEDLEY_GCC_HAS_WARNING | |
1033 #endif | |
1034 #if defined(__has_warning) | |
1035 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) | |
1036 #else | |
1037 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
1038 #endif | |
1039 | |
1040 #if \ | |
1041 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ | |
1042 defined(__clang__) || \ | |
1043 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ | |
1044 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1045 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ | |
1046 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ | |
1047 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1048 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1049 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ | |
1050 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ | |
1051 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ | |
1052 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ | |
1053 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1054 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1055 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ | |
1056 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ | |
1057 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ | |
1058 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) | |
1059 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) | |
1060 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) | |
1061 #define JSON_HEDLEY_PRAGMA(value) __pragma(value) | |
1062 #else | |
1063 #define JSON_HEDLEY_PRAGMA(value) | |
1064 #endif | |
1065 | |
1066 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) | |
1067 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH | |
1068 #endif | |
1069 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) | |
1070 #undef JSON_HEDLEY_DIAGNOSTIC_POP | |
1071 #endif | |
1072 #if defined(__clang__) | |
1073 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") | |
1074 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") | |
1075 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
1076 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") | |
1077 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") | |
1078 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) | |
1079 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") | |
1080 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") | |
1081 #elif \ | |
1082 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ | |
1083 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) | |
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) | |
1086 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) | |
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") | |
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") | |
1089 #elif \ | |
1090 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1091 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1092 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ | |
1093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ | |
1094 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1095 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) | |
1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") | |
1097 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") | |
1098 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) | |
1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") | |
1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") | |
1101 #else | |
1102 #define JSON_HEDLEY_DIAGNOSTIC_PUSH | |
1103 #define JSON_HEDLEY_DIAGNOSTIC_POP | |
1104 #endif | |
1105 | |
1106 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for | |
1107 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ | |
1108 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) | |
1109 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ | |
1110 #endif | |
1111 #if defined(__cplusplus) | |
1112 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") | |
1113 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") | |
1114 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") | |
1115 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ | |
1116 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1117 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ | |
1118 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ | |
1119 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ | |
1120 xpr \ | |
1121 JSON_HEDLEY_DIAGNOSTIC_POP | |
1122 # else | |
1123 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ | |
1124 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1125 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ | |
1126 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ | |
1127 xpr \ | |
1128 JSON_HEDLEY_DIAGNOSTIC_POP | |
1129 # endif | |
1130 # else | |
1131 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ | |
1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ | |
1134 xpr \ | |
1135 JSON_HEDLEY_DIAGNOSTIC_POP | |
1136 # endif | |
1137 # endif | |
1138 #endif | |
1139 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) | |
1140 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x | |
1141 #endif | |
1142 | |
1143 #if defined(JSON_HEDLEY_CONST_CAST) | |
1144 #undef JSON_HEDLEY_CONST_CAST | |
1145 #endif | |
1146 #if defined(__cplusplus) | |
1147 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr)) | |
1148 #elif \ | |
1149 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ | |
1150 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ | |
1151 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
1152 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ | |
1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1154 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ | |
1155 ((T) (expr)); \ | |
1156 JSON_HEDLEY_DIAGNOSTIC_POP \ | |
1157 })) | |
1158 #else | |
1159 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) | |
1160 #endif | |
1161 | |
1162 #if defined(JSON_HEDLEY_REINTERPRET_CAST) | |
1163 #undef JSON_HEDLEY_REINTERPRET_CAST | |
1164 #endif | |
1165 #if defined(__cplusplus) | |
1166 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr)) | |
1167 #else | |
1168 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) | |
1169 #endif | |
1170 | |
1171 #if defined(JSON_HEDLEY_STATIC_CAST) | |
1172 #undef JSON_HEDLEY_STATIC_CAST | |
1173 #endif | |
1174 #if defined(__cplusplus) | |
1175 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr)) | |
1176 #else | |
1177 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) | |
1178 #endif | |
1179 | |
1180 #if defined(JSON_HEDLEY_CPP_CAST) | |
1181 #undef JSON_HEDLEY_CPP_CAST | |
1182 #endif | |
1183 #if defined(__cplusplus) | |
1184 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") | |
1185 # define JSON_HEDLEY_CPP_CAST(T, expr) \ | |
1186 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1187 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ | |
1188 ((T) (expr)) \ | |
1189 JSON_HEDLEY_DIAGNOSTIC_POP | |
1190 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) | |
1191 # define JSON_HEDLEY_CPP_CAST(T, expr) \ | |
1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
1193 _Pragma("diag_suppress=Pe137") \ | |
1194 JSON_HEDLEY_DIAGNOSTIC_POP | |
1195 # else | |
1196 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) | |
1197 # endif | |
1198 #else | |
1199 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr) | |
1200 #endif | |
1201 | |
1202 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) | |
1203 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED | |
1204 #endif | |
1205 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") | |
1206 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") | |
1207 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
1208 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") | |
1209 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) | |
1211 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) | |
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") | |
1213 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) | |
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") | |
1215 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) | |
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") | |
1217 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) | |
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) | |
1219 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") | |
1221 #elif \ | |
1222 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1223 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1224 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1225 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1226 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1227 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1228 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1229 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1230 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1231 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1232 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) | |
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") | |
1234 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) | |
1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") | |
1236 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) | |
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") | |
1238 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") | |
1240 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) | |
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") | |
1242 #else | |
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED | |
1244 #endif | |
1245 | |
1246 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) | |
1247 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS | |
1248 #endif | |
1249 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") | |
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") | |
1251 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") | |
1253 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) | |
1255 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) | |
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") | |
1257 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) | |
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") | |
1259 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) | |
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) | |
1261 #elif \ | |
1262 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ | |
1263 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ | |
1264 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1265 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) | |
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") | |
1267 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) | |
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") | |
1269 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") | |
1271 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") | |
1273 #else | |
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS | |
1275 #endif | |
1276 | |
1277 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) | |
1278 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES | |
1279 #endif | |
1280 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") | |
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") | |
1282 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) | |
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") | |
1284 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) | |
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") | |
1286 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) | |
1288 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) | |
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) | |
1290 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) | |
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") | |
1292 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) | |
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") | |
1294 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) | |
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") | |
1296 #elif \ | |
1297 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ | |
1298 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ | |
1299 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) | |
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") | |
1301 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") | |
1303 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") | |
1305 #else | |
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES | |
1307 #endif | |
1308 | |
1309 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) | |
1310 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL | |
1311 #endif | |
1312 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") | |
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") | |
1314 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") | |
1316 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) | |
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") | |
1318 #else | |
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL | |
1320 #endif | |
1321 | |
1322 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) | |
1323 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION | |
1324 #endif | |
1325 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function") | |
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") | |
1327 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) | |
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") | |
1329 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) | |
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) | |
1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") | |
1333 #else | |
1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION | |
1335 #endif | |
1336 | |
1337 #if defined(JSON_HEDLEY_DEPRECATED) | |
1338 #undef JSON_HEDLEY_DEPRECATED | |
1339 #endif | |
1340 #if defined(JSON_HEDLEY_DEPRECATED_FOR) | |
1341 #undef JSON_HEDLEY_DEPRECATED_FOR | |
1342 #endif | |
1343 #if \ | |
1344 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ | |
1345 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1346 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) | |
1347 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) | |
1348 #elif \ | |
1349 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ | |
1350 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ | |
1351 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1352 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ | |
1353 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ | |
1354 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ | |
1355 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ | |
1356 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ | |
1357 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ | |
1358 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1359 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ | |
1360 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1361 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) | |
1362 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) | |
1363 #elif defined(__cplusplus) && (__cplusplus >= 201402L) | |
1364 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) | |
1365 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) | |
1366 #elif \ | |
1367 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ | |
1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ | |
1369 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1370 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1371 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1373 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1374 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1375 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1376 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1377 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1378 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1379 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1380 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1381 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ | |
1382 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) | |
1383 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) | |
1384 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) | |
1385 #elif \ | |
1386 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ | |
1387 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ | |
1388 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1389 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) | |
1390 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) | |
1391 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1392 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") | |
1393 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") | |
1394 #else | |
1395 #define JSON_HEDLEY_DEPRECATED(since) | |
1396 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) | |
1397 #endif | |
1398 | |
1399 #if defined(JSON_HEDLEY_UNAVAILABLE) | |
1400 #undef JSON_HEDLEY_UNAVAILABLE | |
1401 #endif | |
1402 #if \ | |
1403 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ | |
1404 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ | |
1405 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1406 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1407 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) | |
1408 #else | |
1409 #define JSON_HEDLEY_UNAVAILABLE(available_since) | |
1410 #endif | |
1411 | |
1412 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) | |
1413 #undef JSON_HEDLEY_WARN_UNUSED_RESULT | |
1414 #endif | |
1415 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) | |
1416 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG | |
1417 #endif | |
1418 #if \ | |
1419 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ | |
1420 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ | |
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1422 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1423 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1424 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1425 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1426 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1427 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1428 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1429 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1430 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1431 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1432 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1433 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ | |
1434 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ | |
1435 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1436 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) | |
1437 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) | |
1438 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) | |
1439 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) | |
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) | |
1441 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) | |
1442 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) | |
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) | |
1444 #elif defined(_Check_return_) /* SAL */ | |
1445 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ | |
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ | |
1447 #else | |
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT | |
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) | |
1450 #endif | |
1451 | |
1452 #if defined(JSON_HEDLEY_SENTINEL) | |
1453 #undef JSON_HEDLEY_SENTINEL | |
1454 #endif | |
1455 #if \ | |
1456 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ | |
1457 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ | |
1458 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1459 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ | |
1460 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1461 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) | |
1462 #else | |
1463 #define JSON_HEDLEY_SENTINEL(position) | |
1464 #endif | |
1465 | |
1466 #if defined(JSON_HEDLEY_NO_RETURN) | |
1467 #undef JSON_HEDLEY_NO_RETURN | |
1468 #endif | |
1469 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1470 #define JSON_HEDLEY_NO_RETURN __noreturn | |
1471 #elif \ | |
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1474 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) | |
1475 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L | |
1476 #define JSON_HEDLEY_NO_RETURN _Noreturn | |
1477 #elif defined(__cplusplus) && (__cplusplus >= 201103L) | |
1478 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) | |
1479 #elif \ | |
1480 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ | |
1481 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ | |
1482 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1483 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1484 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1485 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1486 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1487 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1488 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1489 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1490 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1491 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1492 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1493 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1494 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1495 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1496 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) | |
1497 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) | |
1498 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) | |
1499 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") | |
1500 #elif \ | |
1501 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ | |
1502 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1503 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) | |
1504 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) | |
1505 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") | |
1506 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) | |
1507 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) | |
1508 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) | |
1509 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) | |
1510 #else | |
1511 #define JSON_HEDLEY_NO_RETURN | |
1512 #endif | |
1513 | |
1514 #if defined(JSON_HEDLEY_NO_ESCAPE) | |
1515 #undef JSON_HEDLEY_NO_ESCAPE | |
1516 #endif | |
1517 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) | |
1518 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) | |
1519 #else | |
1520 #define JSON_HEDLEY_NO_ESCAPE | |
1521 #endif | |
1522 | |
1523 #if defined(JSON_HEDLEY_UNREACHABLE) | |
1524 #undef JSON_HEDLEY_UNREACHABLE | |
1525 #endif | |
1526 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) | |
1527 #undef JSON_HEDLEY_UNREACHABLE_RETURN | |
1528 #endif | |
1529 #if defined(JSON_HEDLEY_ASSUME) | |
1530 #undef JSON_HEDLEY_ASSUME | |
1531 #endif | |
1532 #if \ | |
1533 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ | |
1534 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1535 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1536 #define JSON_HEDLEY_ASSUME(expr) __assume(expr) | |
1537 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) | |
1538 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) | |
1539 #elif \ | |
1540 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ | |
1541 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) | |
1542 #if defined(__cplusplus) | |
1543 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) | |
1544 #else | |
1545 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) | |
1546 #endif | |
1547 #endif | |
1548 #if \ | |
1549 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ | |
1550 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ | |
1551 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ | |
1552 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1553 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ | |
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ | |
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1556 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() | |
1557 #elif defined(JSON_HEDLEY_ASSUME) | |
1558 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) | |
1559 #endif | |
1560 #if !defined(JSON_HEDLEY_ASSUME) | |
1561 #if defined(JSON_HEDLEY_UNREACHABLE) | |
1562 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) | |
1563 #else | |
1564 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) | |
1565 #endif | |
1566 #endif | |
1567 #if defined(JSON_HEDLEY_UNREACHABLE) | |
1568 #if \ | |
1569 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ | |
1570 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) | |
1571 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) | |
1572 #else | |
1573 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() | |
1574 #endif | |
1575 #else | |
1576 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) | |
1577 #endif | |
1578 #if !defined(JSON_HEDLEY_UNREACHABLE) | |
1579 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) | |
1580 #endif | |
1581 | |
1582 JSON_HEDLEY_DIAGNOSTIC_PUSH | |
1583 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic") | |
1584 #pragma clang diagnostic ignored "-Wpedantic" | |
1585 #endif | |
1586 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) | |
1587 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" | |
1588 #endif | |
1589 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) | |
1590 #if defined(__clang__) | |
1591 #pragma clang diagnostic ignored "-Wvariadic-macros" | |
1592 #elif defined(JSON_HEDLEY_GCC_VERSION) | |
1593 #pragma GCC diagnostic ignored "-Wvariadic-macros" | |
1594 #endif | |
1595 #endif | |
1596 #if defined(JSON_HEDLEY_NON_NULL) | |
1597 #undef JSON_HEDLEY_NON_NULL | |
1598 #endif | |
1599 #if \ | |
1600 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ | |
1601 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ | |
1602 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1603 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) | |
1604 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) | |
1605 #else | |
1606 #define JSON_HEDLEY_NON_NULL(...) | |
1607 #endif | |
1608 JSON_HEDLEY_DIAGNOSTIC_POP | |
1609 | |
1610 #if defined(JSON_HEDLEY_PRINTF_FORMAT) | |
1611 #undef JSON_HEDLEY_PRINTF_FORMAT | |
1612 #endif | |
1613 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) | |
1614 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) | |
1615 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) | |
1616 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) | |
1617 #elif \ | |
1618 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ | |
1619 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ | |
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1621 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ | |
1622 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1623 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1624 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1625 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1626 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1627 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1628 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1629 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1630 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1631 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1632 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1633 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1634 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1635 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) | |
1636 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) | |
1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) | |
1638 #else | |
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) | |
1640 #endif | |
1641 | |
1642 #if defined(JSON_HEDLEY_CONSTEXPR) | |
1643 #undef JSON_HEDLEY_CONSTEXPR | |
1644 #endif | |
1645 #if defined(__cplusplus) | |
1646 #if __cplusplus >= 201103L | |
1647 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) | |
1648 #endif | |
1649 #endif | |
1650 #if !defined(JSON_HEDLEY_CONSTEXPR) | |
1651 #define JSON_HEDLEY_CONSTEXPR | |
1652 #endif | |
1653 | |
1654 #if defined(JSON_HEDLEY_PREDICT) | |
1655 #undef JSON_HEDLEY_PREDICT | |
1656 #endif | |
1657 #if defined(JSON_HEDLEY_LIKELY) | |
1658 #undef JSON_HEDLEY_LIKELY | |
1659 #endif | |
1660 #if defined(JSON_HEDLEY_UNLIKELY) | |
1661 #undef JSON_HEDLEY_UNLIKELY | |
1662 #endif | |
1663 #if defined(JSON_HEDLEY_UNPREDICTABLE) | |
1664 #undef JSON_HEDLEY_UNPREDICTABLE | |
1665 #endif | |
1666 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) | |
1667 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) | |
1668 #endif | |
1669 #if \ | |
1670 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ | |
1671 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ | |
1672 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1673 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) | |
1674 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) | |
1675 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) | |
1676 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) | |
1677 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) | |
1678 #elif \ | |
1679 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ | |
1680 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ | |
1681 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1682 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ | |
1683 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1684 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1685 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1686 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ | |
1687 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ | |
1688 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ | |
1689 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ | |
1690 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1691 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1692 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ | |
1693 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ | |
1694 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1695 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ | |
1696 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) | |
1697 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ | |
1698 (__extension__ ({ \ | |
1699 double hedley_probability_ = (probability); \ | |
1700 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ | |
1701 })) | |
1702 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ | |
1703 (__extension__ ({ \ | |
1704 double hedley_probability_ = (probability); \ | |
1705 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ | |
1706 })) | |
1707 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) | |
1708 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) | |
1709 #else | |
1710 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) | |
1711 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) | |
1712 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) | |
1713 # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) | |
1714 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) | |
1715 #endif | |
1716 #if !defined(JSON_HEDLEY_UNPREDICTABLE) | |
1717 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) | |
1718 #endif | |
1719 | |
1720 #if defined(JSON_HEDLEY_MALLOC) | |
1721 #undef JSON_HEDLEY_MALLOC | |
1722 #endif | |
1723 #if \ | |
1724 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ | |
1725 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ | |
1726 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1727 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1728 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1729 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ | |
1730 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1731 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1732 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1733 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1734 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1735 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1736 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1737 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1738 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1739 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1740 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1741 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1742 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) | |
1743 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) | |
1744 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") | |
1745 #elif \ | |
1746 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ | |
1747 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1748 #define JSON_HEDLEY_MALLOC __declspec(restrict) | |
1749 #else | |
1750 #define JSON_HEDLEY_MALLOC | |
1751 #endif | |
1752 | |
1753 #if defined(JSON_HEDLEY_PURE) | |
1754 #undef JSON_HEDLEY_PURE | |
1755 #endif | |
1756 #if \ | |
1757 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ | |
1758 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ | |
1759 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1760 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1761 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1762 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1763 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1764 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1765 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1766 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1767 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1768 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1769 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1770 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1771 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1772 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1773 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1774 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ | |
1775 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1776 # define JSON_HEDLEY_PURE __attribute__((__pure__)) | |
1777 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) | |
1778 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") | |
1779 #elif defined(__cplusplus) && \ | |
1780 ( \ | |
1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ | |
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ | |
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ | |
1784 ) | |
1785 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") | |
1786 #else | |
1787 # define JSON_HEDLEY_PURE | |
1788 #endif | |
1789 | |
1790 #if defined(JSON_HEDLEY_CONST) | |
1791 #undef JSON_HEDLEY_CONST | |
1792 #endif | |
1793 #if \ | |
1794 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ | |
1795 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ | |
1796 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1797 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1798 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1799 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1800 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1801 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1802 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1803 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1804 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1805 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1806 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1807 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1808 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1809 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1810 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1811 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ | |
1812 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1813 #define JSON_HEDLEY_CONST __attribute__((__const__)) | |
1814 #elif \ | |
1815 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) | |
1816 #define JSON_HEDLEY_CONST _Pragma("no_side_effect") | |
1817 #else | |
1818 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE | |
1819 #endif | |
1820 | |
1821 #if defined(JSON_HEDLEY_RESTRICT) | |
1822 #undef JSON_HEDLEY_RESTRICT | |
1823 #endif | |
1824 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) | |
1825 #define JSON_HEDLEY_RESTRICT restrict | |
1826 #elif \ | |
1827 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ | |
1828 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ | |
1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1830 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ | |
1831 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1832 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1833 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ | |
1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ | |
1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ | |
1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1838 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ | |
1839 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ | |
1840 defined(__clang__) || \ | |
1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1842 #define JSON_HEDLEY_RESTRICT __restrict | |
1843 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) | |
1844 #define JSON_HEDLEY_RESTRICT _Restrict | |
1845 #else | |
1846 #define JSON_HEDLEY_RESTRICT | |
1847 #endif | |
1848 | |
1849 #if defined(JSON_HEDLEY_INLINE) | |
1850 #undef JSON_HEDLEY_INLINE | |
1851 #endif | |
1852 #if \ | |
1853 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ | |
1854 (defined(__cplusplus) && (__cplusplus >= 199711L)) | |
1855 #define JSON_HEDLEY_INLINE inline | |
1856 #elif \ | |
1857 defined(JSON_HEDLEY_GCC_VERSION) || \ | |
1858 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) | |
1859 #define JSON_HEDLEY_INLINE __inline__ | |
1860 #elif \ | |
1861 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ | |
1862 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ | |
1863 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ | |
1865 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ | |
1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ | |
1867 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ | |
1868 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1869 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1870 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1871 #define JSON_HEDLEY_INLINE __inline | |
1872 #else | |
1873 #define JSON_HEDLEY_INLINE | |
1874 #endif | |
1875 | |
1876 #if defined(JSON_HEDLEY_ALWAYS_INLINE) | |
1877 #undef JSON_HEDLEY_ALWAYS_INLINE | |
1878 #endif | |
1879 #if \ | |
1880 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ | |
1881 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ | |
1882 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1883 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1884 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1885 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1886 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1887 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1889 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1891 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1892 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1893 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1894 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1895 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1896 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1897 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ | |
1898 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) | |
1899 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE | |
1900 #elif \ | |
1901 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ | |
1902 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1903 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline | |
1904 #elif defined(__cplusplus) && \ | |
1905 ( \ | |
1906 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1907 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1908 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ | |
1910 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1911 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ | |
1912 ) | |
1913 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") | |
1914 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1915 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") | |
1916 #else | |
1917 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE | |
1918 #endif | |
1919 | |
1920 #if defined(JSON_HEDLEY_NEVER_INLINE) | |
1921 #undef JSON_HEDLEY_NEVER_INLINE | |
1922 #endif | |
1923 #if \ | |
1924 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ | |
1925 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ | |
1926 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1927 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1928 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1929 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ | |
1930 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ | |
1931 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1932 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ | |
1933 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1934 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ | |
1935 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1936 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ | |
1937 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1938 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ | |
1939 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ | |
1940 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ | |
1941 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ | |
1942 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) | |
1943 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) | |
1944 #elif \ | |
1945 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ | |
1946 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
1947 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) | |
1948 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) | |
1949 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") | |
1950 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) | |
1951 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") | |
1952 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") | |
1954 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) | |
1955 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) | |
1956 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) | |
1957 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) | |
1958 #else | |
1959 #define JSON_HEDLEY_NEVER_INLINE | |
1960 #endif | |
1961 | |
1962 #if defined(JSON_HEDLEY_PRIVATE) | |
1963 #undef JSON_HEDLEY_PRIVATE | |
1964 #endif | |
1965 #if defined(JSON_HEDLEY_PUBLIC) | |
1966 #undef JSON_HEDLEY_PUBLIC | |
1967 #endif | |
1968 #if defined(JSON_HEDLEY_IMPORT) | |
1969 #undef JSON_HEDLEY_IMPORT | |
1970 #endif | |
1971 #if defined(_WIN32) || defined(__CYGWIN__) | |
1972 # define JSON_HEDLEY_PRIVATE | |
1973 # define JSON_HEDLEY_PUBLIC __declspec(dllexport) | |
1974 # define JSON_HEDLEY_IMPORT __declspec(dllimport) | |
1975 #else | |
1976 # if \ | |
1977 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ | |
1978 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ | |
1979 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ | |
1980 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
1981 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
1982 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ | |
1983 ( \ | |
1984 defined(__TI_EABI__) && \ | |
1985 ( \ | |
1986 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ | |
1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ | |
1988 ) \ | |
1989 ) || \ | |
1990 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
1991 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) | |
1992 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) | |
1993 # else | |
1994 # define JSON_HEDLEY_PRIVATE | |
1995 # define JSON_HEDLEY_PUBLIC | |
1996 # endif | |
1997 # define JSON_HEDLEY_IMPORT extern | |
1998 #endif | |
1999 | |
2000 #if defined(JSON_HEDLEY_NO_THROW) | |
2001 #undef JSON_HEDLEY_NO_THROW | |
2002 #endif | |
2003 #if \ | |
2004 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ | |
2005 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ | |
2006 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
2007 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
2008 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) | |
2009 #elif \ | |
2010 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ | |
2011 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ | |
2012 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) | |
2013 #define JSON_HEDLEY_NO_THROW __declspec(nothrow) | |
2014 #else | |
2015 #define JSON_HEDLEY_NO_THROW | |
2016 #endif | |
2017 | |
2018 #if defined(JSON_HEDLEY_FALL_THROUGH) | |
2019 #undef JSON_HEDLEY_FALL_THROUGH | |
2020 #endif | |
2021 #if \ | |
2022 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ | |
2023 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ | |
2024 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
2025 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) | |
2026 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) | |
2027 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) | |
2028 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) | |
2029 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) | |
2030 #elif defined(__fallthrough) /* SAL */ | |
2031 #define JSON_HEDLEY_FALL_THROUGH __fallthrough | |
2032 #else | |
2033 #define JSON_HEDLEY_FALL_THROUGH | |
2034 #endif | |
2035 | |
2036 #if defined(JSON_HEDLEY_RETURNS_NON_NULL) | |
2037 #undef JSON_HEDLEY_RETURNS_NON_NULL | |
2038 #endif | |
2039 #if \ | |
2040 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ | |
2041 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ | |
2042 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
2043 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) | |
2044 #elif defined(_Ret_notnull_) /* SAL */ | |
2045 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ | |
2046 #else | |
2047 #define JSON_HEDLEY_RETURNS_NON_NULL | |
2048 #endif | |
2049 | |
2050 #if defined(JSON_HEDLEY_ARRAY_PARAM) | |
2051 #undef JSON_HEDLEY_ARRAY_PARAM | |
2052 #endif | |
2053 #if \ | |
2054 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ | |
2055 !defined(__STDC_NO_VLA__) && \ | |
2056 !defined(__cplusplus) && \ | |
2057 !defined(JSON_HEDLEY_PGI_VERSION) && \ | |
2058 !defined(JSON_HEDLEY_TINYC_VERSION) | |
2059 #define JSON_HEDLEY_ARRAY_PARAM(name) (name) | |
2060 #else | |
2061 #define JSON_HEDLEY_ARRAY_PARAM(name) | |
2062 #endif | |
2063 | |
2064 #if defined(JSON_HEDLEY_IS_CONSTANT) | |
2065 #undef JSON_HEDLEY_IS_CONSTANT | |
2066 #endif | |
2067 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) | |
2068 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR | |
2069 #endif | |
2070 /* JSON_HEDLEY_IS_CONSTEXPR_ is for | |
2071 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ | |
2072 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) | |
2073 #undef JSON_HEDLEY_IS_CONSTEXPR_ | |
2074 #endif | |
2075 #if \ | |
2076 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ | |
2077 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ | |
2078 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
2079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ | |
2080 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ | |
2081 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ | |
2082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ | |
2083 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ | |
2084 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ | |
2085 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) | |
2086 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) | |
2087 #endif | |
2088 #if !defined(__cplusplus) | |
2089 # if \ | |
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ | |
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ | |
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ | |
2094 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ | |
2095 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ | |
2096 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) | |
2097 #if defined(__INTPTR_TYPE__) | |
2098 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) | |
2099 #else | |
2100 #include <stdint.h> | |
2101 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) | |
2102 #endif | |
2103 # elif \ | |
2104 ( \ | |
2105 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ | |
2106 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ | |
2107 !defined(JSON_HEDLEY_PGI_VERSION) && \ | |
2108 !defined(JSON_HEDLEY_IAR_VERSION)) || \ | |
2109 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ | |
2110 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ | |
2111 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ | |
2112 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ | |
2113 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) | |
2114 #if defined(__INTPTR_TYPE__) | |
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) | |
2116 #else | |
2117 #include <stdint.h> | |
2118 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) | |
2119 #endif | |
2120 # elif \ | |
2121 defined(JSON_HEDLEY_GCC_VERSION) || \ | |
2122 defined(JSON_HEDLEY_INTEL_VERSION) || \ | |
2123 defined(JSON_HEDLEY_TINYC_VERSION) || \ | |
2124 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ | |
2125 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ | |
2126 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ | |
2127 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ | |
2128 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ | |
2129 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ | |
2130 defined(__clang__) | |
2131 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ | |
2132 sizeof(void) != \ | |
2133 sizeof(*( \ | |
2134 1 ? \ | |
2135 ((void*) ((expr) * 0L) ) : \ | |
2136 ((struct { char v[sizeof(void) * 2]; } *) 1) \ | |
2137 ) \ | |
2138 ) \ | |
2139 ) | |
2140 # endif | |
2141 #endif | |
2142 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) | |
2143 #if !defined(JSON_HEDLEY_IS_CONSTANT) | |
2144 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) | |
2145 #endif | |
2146 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) | |
2147 #else | |
2148 #if !defined(JSON_HEDLEY_IS_CONSTANT) | |
2149 #define JSON_HEDLEY_IS_CONSTANT(expr) (0) | |
2150 #endif | |
2151 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) | |
2152 #endif | |
2153 | |
2154 #if defined(JSON_HEDLEY_BEGIN_C_DECLS) | |
2155 #undef JSON_HEDLEY_BEGIN_C_DECLS | |
2156 #endif | |
2157 #if defined(JSON_HEDLEY_END_C_DECLS) | |
2158 #undef JSON_HEDLEY_END_C_DECLS | |
2159 #endif | |
2160 #if defined(JSON_HEDLEY_C_DECL) | |
2161 #undef JSON_HEDLEY_C_DECL | |
2162 #endif | |
2163 #if defined(__cplusplus) | |
2164 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { | |
2165 #define JSON_HEDLEY_END_C_DECLS } | |
2166 #define JSON_HEDLEY_C_DECL extern "C" | |
2167 #else | |
2168 #define JSON_HEDLEY_BEGIN_C_DECLS | |
2169 #define JSON_HEDLEY_END_C_DECLS | |
2170 #define JSON_HEDLEY_C_DECL | |
2171 #endif | |
2172 | |
2173 #if defined(JSON_HEDLEY_STATIC_ASSERT) | |
2174 #undef JSON_HEDLEY_STATIC_ASSERT | |
2175 #endif | |
2176 #if \ | |
2177 !defined(__cplusplus) && ( \ | |
2178 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ | |
2179 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ | |
2180 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ | |
2181 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ | |
2182 defined(_Static_assert) \ | |
2183 ) | |
2184 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) | |
2185 #elif \ | |
2186 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ | |
2187 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ | |
2188 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
2189 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) | |
2190 #else | |
2191 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) | |
2192 #endif | |
2193 | |
2194 #if defined(JSON_HEDLEY_NULL) | |
2195 #undef JSON_HEDLEY_NULL | |
2196 #endif | |
2197 #if defined(__cplusplus) | |
2198 #if __cplusplus >= 201103L | |
2199 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) | |
2200 #elif defined(NULL) | |
2201 #define JSON_HEDLEY_NULL NULL | |
2202 #else | |
2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) | |
2204 #endif | |
2205 #elif defined(NULL) | |
2206 #define JSON_HEDLEY_NULL NULL | |
2207 #else | |
2208 #define JSON_HEDLEY_NULL ((void*) 0) | |
2209 #endif | |
2210 | |
2211 #if defined(JSON_HEDLEY_MESSAGE) | |
2212 #undef JSON_HEDLEY_MESSAGE | |
2213 #endif | |
2214 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") | |
2215 # define JSON_HEDLEY_MESSAGE(msg) \ | |
2216 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
2217 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ | |
2218 JSON_HEDLEY_PRAGMA(message msg) \ | |
2219 JSON_HEDLEY_DIAGNOSTIC_POP | |
2220 #elif \ | |
2221 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ | |
2222 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
2223 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) | |
2224 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) | |
2225 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) | |
2226 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) | |
2227 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) | |
2228 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) | |
2229 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) | |
2230 #else | |
2231 # define JSON_HEDLEY_MESSAGE(msg) | |
2232 #endif | |
2233 | |
2234 #if defined(JSON_HEDLEY_WARNING) | |
2235 #undef JSON_HEDLEY_WARNING | |
2236 #endif | |
2237 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") | |
2238 # define JSON_HEDLEY_WARNING(msg) \ | |
2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ | |
2241 JSON_HEDLEY_PRAGMA(clang warning msg) \ | |
2242 JSON_HEDLEY_DIAGNOSTIC_POP | |
2243 #elif \ | |
2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ | |
2245 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ | |
2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) | |
2247 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) | |
2248 #elif \ | |
2249 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ | |
2250 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
2251 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) | |
2252 #else | |
2253 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) | |
2254 #endif | |
2255 | |
2256 #if defined(JSON_HEDLEY_REQUIRE) | |
2257 #undef JSON_HEDLEY_REQUIRE | |
2258 #endif | |
2259 #if defined(JSON_HEDLEY_REQUIRE_MSG) | |
2260 #undef JSON_HEDLEY_REQUIRE_MSG | |
2261 #endif | |
2262 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) | |
2263 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") | |
2264 # define JSON_HEDLEY_REQUIRE(expr) \ | |
2265 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
2266 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ | |
2267 __attribute__((diagnose_if(!(expr), #expr, "error"))) \ | |
2268 JSON_HEDLEY_DIAGNOSTIC_POP | |
2269 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ | |
2270 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
2271 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ | |
2272 __attribute__((diagnose_if(!(expr), msg, "error"))) \ | |
2273 JSON_HEDLEY_DIAGNOSTIC_POP | |
2274 # else | |
2275 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) | |
2276 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) | |
2277 # endif | |
2278 #else | |
2279 # define JSON_HEDLEY_REQUIRE(expr) | |
2280 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) | |
2281 #endif | |
2282 | |
2283 #if defined(JSON_HEDLEY_FLAGS) | |
2284 #undef JSON_HEDLEY_FLAGS | |
2285 #endif | |
2286 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) | |
2287 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) | |
2288 #else | |
2289 #define JSON_HEDLEY_FLAGS | |
2290 #endif | |
2291 | |
2292 #if defined(JSON_HEDLEY_FLAGS_CAST) | |
2293 #undef JSON_HEDLEY_FLAGS_CAST | |
2294 #endif | |
2295 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) | |
2296 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ | |
2297 JSON_HEDLEY_DIAGNOSTIC_PUSH \ | |
2298 _Pragma("warning(disable:188)") \ | |
2299 ((T) (expr)); \ | |
2300 JSON_HEDLEY_DIAGNOSTIC_POP \ | |
2301 })) | |
2302 #else | |
2303 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) | |
2304 #endif | |
2305 | |
2306 #if defined(JSON_HEDLEY_EMPTY_BASES) | |
2307 #undef JSON_HEDLEY_EMPTY_BASES | |
2308 #endif | |
2309 #if \ | |
2310 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ | |
2311 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) | |
2312 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) | |
2313 #else | |
2314 #define JSON_HEDLEY_EMPTY_BASES | |
2315 #endif | |
2316 | |
2317 /* Remaining macros are deprecated. */ | |
2318 | |
2319 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) | |
2320 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK | |
2321 #endif | |
2322 #if defined(__clang__) | |
2323 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) | |
2324 #else | |
2325 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) | |
2326 #endif | |
2327 | |
2328 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) | |
2329 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE | |
2330 #endif | |
2331 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) | |
2332 | |
2333 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) | |
2334 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE | |
2335 #endif | |
2336 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) | |
2337 | |
2338 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) | |
2339 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN | |
2340 #endif | |
2341 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) | |
2342 | |
2343 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) | |
2344 #undef JSON_HEDLEY_CLANG_HAS_FEATURE | |
2345 #endif | |
2346 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) | |
2347 | |
2348 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) | |
2349 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION | |
2350 #endif | |
2351 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) | |
2352 | |
2353 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) | |
2354 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE | |
2355 #endif | |
2356 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) | |
2357 | |
2358 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING) | |
2359 #undef JSON_HEDLEY_CLANG_HAS_WARNING | |
2360 #endif | |
2361 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) | |
2362 | |
2363 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ | |
2364 | |
2365 | |
2366 // This file contains all internal macro definitions (except those affecting ABI) | |
2367 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them | |
2368 | |
2369 // #include <nlohmann/detail/abi_macros.hpp> | |
2370 | |
2371 | |
2372 // exclude unsupported compilers | |
2373 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) | |
2374 #if defined(__clang__) | |
2375 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 | |
2376 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" | |
2377 #endif | |
2378 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) | |
2379 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 | |
2380 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" | |
2381 #endif | |
2382 #endif | |
2383 #endif | |
2384 | |
2385 // C++ language standard detection | |
2386 // if the user manually specified the used c++ version this is skipped | |
2387 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) | |
2388 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) | |
2389 #define JSON_HAS_CPP_20 | |
2390 #define JSON_HAS_CPP_17 | |
2391 #define JSON_HAS_CPP_14 | |
2392 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 | |
2393 #define JSON_HAS_CPP_17 | |
2394 #define JSON_HAS_CPP_14 | |
2395 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) | |
2396 #define JSON_HAS_CPP_14 | |
2397 #endif | |
2398 // the cpp 11 flag is always specified because it is the minimal required version | |
2399 #define JSON_HAS_CPP_11 | |
2400 #endif | |
2401 | |
2402 #ifdef __has_include | |
2403 #if __has_include(<version>) | |
2404 #include <version> | |
2405 #endif | |
2406 #endif | |
2407 | |
2408 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) | |
2409 #ifdef JSON_HAS_CPP_17 | |
2410 #if defined(__cpp_lib_filesystem) | |
2411 #define JSON_HAS_FILESYSTEM 1 | |
2412 #elif defined(__cpp_lib_experimental_filesystem) | |
2413 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | |
2414 #elif !defined(__has_include) | |
2415 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | |
2416 #elif __has_include(<filesystem>) | |
2417 #define JSON_HAS_FILESYSTEM 1 | |
2418 #elif __has_include(<experimental/filesystem>) | |
2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 | |
2420 #endif | |
2421 | |
2422 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ | |
2423 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 | |
2424 #undef JSON_HAS_FILESYSTEM | |
2425 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2426 #endif | |
2427 | |
2428 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support | |
2429 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 | |
2430 #undef JSON_HAS_FILESYSTEM | |
2431 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2432 #endif | |
2433 | |
2434 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support | |
2435 #if defined(__clang_major__) && __clang_major__ < 7 | |
2436 #undef JSON_HAS_FILESYSTEM | |
2437 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2438 #endif | |
2439 | |
2440 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support | |
2441 #if defined(_MSC_VER) && _MSC_VER < 1914 | |
2442 #undef JSON_HAS_FILESYSTEM | |
2443 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2444 #endif | |
2445 | |
2446 // no filesystem support before iOS 13 | |
2447 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 | |
2448 #undef JSON_HAS_FILESYSTEM | |
2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2450 #endif | |
2451 | |
2452 // no filesystem support before macOS Catalina | |
2453 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 | |
2454 #undef JSON_HAS_FILESYSTEM | |
2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2456 #endif | |
2457 #endif | |
2458 #endif | |
2459 | |
2460 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
2461 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 | |
2462 #endif | |
2463 | |
2464 #ifndef JSON_HAS_FILESYSTEM | |
2465 #define JSON_HAS_FILESYSTEM 0 | |
2466 #endif | |
2467 | |
2468 #ifndef JSON_HAS_THREE_WAY_COMPARISON | |
2469 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ | |
2470 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L | |
2471 #define JSON_HAS_THREE_WAY_COMPARISON 1 | |
2472 #else | |
2473 #define JSON_HAS_THREE_WAY_COMPARISON 0 | |
2474 #endif | |
2475 #endif | |
2476 | |
2477 #ifndef JSON_HAS_RANGES | |
2478 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error | |
2479 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 | |
2480 #define JSON_HAS_RANGES 0 | |
2481 #elif defined(__cpp_lib_ranges) | |
2482 #define JSON_HAS_RANGES 1 | |
2483 #else | |
2484 #define JSON_HAS_RANGES 0 | |
2485 #endif | |
2486 #endif | |
2487 | |
2488 #ifndef JSON_HAS_STATIC_RTTI | |
2489 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 | |
2490 #define JSON_HAS_STATIC_RTTI 1 | |
2491 #else | |
2492 #define JSON_HAS_STATIC_RTTI 0 | |
2493 #endif | |
2494 #endif | |
2495 | |
2496 #ifdef JSON_HAS_CPP_17 | |
2497 #define JSON_INLINE_VARIABLE inline | |
2498 #else | |
2499 #define JSON_INLINE_VARIABLE | |
2500 #endif | |
2501 | |
2502 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) | |
2503 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] | |
2504 #else | |
2505 #define JSON_NO_UNIQUE_ADDRESS | |
2506 #endif | |
2507 | |
2508 // disable documentation warnings on clang | |
2509 #if defined(__clang__) | |
2510 #pragma clang diagnostic push | |
2511 #pragma clang diagnostic ignored "-Wdocumentation" | |
2512 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" | |
2513 #endif | |
2514 | |
2515 // allow disabling exceptions | |
2516 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) | |
2517 #define JSON_THROW(exception) throw exception | |
2518 #define JSON_TRY try | |
2519 #define JSON_CATCH(exception) catch(exception) | |
2520 #define JSON_INTERNAL_CATCH(exception) catch(exception) | |
2521 #else | |
2522 #include <cstdlib> | |
2523 #define JSON_THROW(exception) std::abort() | |
2524 #define JSON_TRY if(true) | |
2525 #define JSON_CATCH(exception) if(false) | |
2526 #define JSON_INTERNAL_CATCH(exception) if(false) | |
2527 #endif | |
2528 | |
2529 // override exception macros | |
2530 #if defined(JSON_THROW_USER) | |
2531 #undef JSON_THROW | |
2532 #define JSON_THROW JSON_THROW_USER | |
2533 #endif | |
2534 #if defined(JSON_TRY_USER) | |
2535 #undef JSON_TRY | |
2536 #define JSON_TRY JSON_TRY_USER | |
2537 #endif | |
2538 #if defined(JSON_CATCH_USER) | |
2539 #undef JSON_CATCH | |
2540 #define JSON_CATCH JSON_CATCH_USER | |
2541 #undef JSON_INTERNAL_CATCH | |
2542 #define JSON_INTERNAL_CATCH JSON_CATCH_USER | |
2543 #endif | |
2544 #if defined(JSON_INTERNAL_CATCH_USER) | |
2545 #undef JSON_INTERNAL_CATCH | |
2546 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER | |
2547 #endif | |
2548 | |
2549 // allow overriding assert | |
2550 #if !defined(JSON_ASSERT) | |
2551 #include <cassert> // assert | |
2552 #define JSON_ASSERT(x) assert(x) | |
2553 #endif | |
2554 | |
2555 // allow to access some private functions (needed by the test suite) | |
2556 #if defined(JSON_TESTS_PRIVATE) | |
2557 #define JSON_PRIVATE_UNLESS_TESTED public | |
2558 #else | |
2559 #define JSON_PRIVATE_UNLESS_TESTED private | |
2560 #endif | |
2561 | |
2562 /*! | |
2563 @brief macro to briefly define a mapping between an enum and JSON | |
2564 @def NLOHMANN_JSON_SERIALIZE_ENUM | |
2565 @since version 3.4.0 | |
2566 */ | |
2567 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ | |
2568 template<typename BasicJsonType> \ | |
2569 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ | |
2570 { \ | |
2571 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ | |
2572 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ | |
2573 auto it = std::find_if(std::begin(m), std::end(m), \ | |
2574 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ | |
2575 { \ | |
2576 return ej_pair.first == e; \ | |
2577 }); \ | |
2578 j = ((it != std::end(m)) ? it : std::begin(m))->second; \ | |
2579 } \ | |
2580 template<typename BasicJsonType> \ | |
2581 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ | |
2582 { \ | |
2583 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ | |
2584 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ | |
2585 auto it = std::find_if(std::begin(m), std::end(m), \ | |
2586 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ | |
2587 { \ | |
2588 return ej_pair.second == j; \ | |
2589 }); \ | |
2590 e = ((it != std::end(m)) ? it : std::begin(m))->first; \ | |
2591 } | |
2592 | |
2593 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They | |
2594 // may be removed in the future once the class is split. | |
2595 | |
2596 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ | |
2597 template<template<typename, typename, typename...> class ObjectType, \ | |
2598 template<typename, typename...> class ArrayType, \ | |
2599 class StringType, class BooleanType, class NumberIntegerType, \ | |
2600 class NumberUnsignedType, class NumberFloatType, \ | |
2601 template<typename> class AllocatorType, \ | |
2602 template<typename, typename = void> class JSONSerializer, \ | |
2603 class BinaryType, \ | |
2604 class CustomBaseClass> | |
2605 | |
2606 #define NLOHMANN_BASIC_JSON_TPL \ | |
2607 basic_json<ObjectType, ArrayType, StringType, BooleanType, \ | |
2608 NumberIntegerType, NumberUnsignedType, NumberFloatType, \ | |
2609 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> | |
2610 | |
2611 // Macros to simplify conversion from/to types | |
2612 | |
2613 #define NLOHMANN_JSON_EXPAND( x ) x | |
2614 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME | |
2615 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ | |
2616 NLOHMANN_JSON_PASTE64, \ | |
2617 NLOHMANN_JSON_PASTE63, \ | |
2618 NLOHMANN_JSON_PASTE62, \ | |
2619 NLOHMANN_JSON_PASTE61, \ | |
2620 NLOHMANN_JSON_PASTE60, \ | |
2621 NLOHMANN_JSON_PASTE59, \ | |
2622 NLOHMANN_JSON_PASTE58, \ | |
2623 NLOHMANN_JSON_PASTE57, \ | |
2624 NLOHMANN_JSON_PASTE56, \ | |
2625 NLOHMANN_JSON_PASTE55, \ | |
2626 NLOHMANN_JSON_PASTE54, \ | |
2627 NLOHMANN_JSON_PASTE53, \ | |
2628 NLOHMANN_JSON_PASTE52, \ | |
2629 NLOHMANN_JSON_PASTE51, \ | |
2630 NLOHMANN_JSON_PASTE50, \ | |
2631 NLOHMANN_JSON_PASTE49, \ | |
2632 NLOHMANN_JSON_PASTE48, \ | |
2633 NLOHMANN_JSON_PASTE47, \ | |
2634 NLOHMANN_JSON_PASTE46, \ | |
2635 NLOHMANN_JSON_PASTE45, \ | |
2636 NLOHMANN_JSON_PASTE44, \ | |
2637 NLOHMANN_JSON_PASTE43, \ | |
2638 NLOHMANN_JSON_PASTE42, \ | |
2639 NLOHMANN_JSON_PASTE41, \ | |
2640 NLOHMANN_JSON_PASTE40, \ | |
2641 NLOHMANN_JSON_PASTE39, \ | |
2642 NLOHMANN_JSON_PASTE38, \ | |
2643 NLOHMANN_JSON_PASTE37, \ | |
2644 NLOHMANN_JSON_PASTE36, \ | |
2645 NLOHMANN_JSON_PASTE35, \ | |
2646 NLOHMANN_JSON_PASTE34, \ | |
2647 NLOHMANN_JSON_PASTE33, \ | |
2648 NLOHMANN_JSON_PASTE32, \ | |
2649 NLOHMANN_JSON_PASTE31, \ | |
2650 NLOHMANN_JSON_PASTE30, \ | |
2651 NLOHMANN_JSON_PASTE29, \ | |
2652 NLOHMANN_JSON_PASTE28, \ | |
2653 NLOHMANN_JSON_PASTE27, \ | |
2654 NLOHMANN_JSON_PASTE26, \ | |
2655 NLOHMANN_JSON_PASTE25, \ | |
2656 NLOHMANN_JSON_PASTE24, \ | |
2657 NLOHMANN_JSON_PASTE23, \ | |
2658 NLOHMANN_JSON_PASTE22, \ | |
2659 NLOHMANN_JSON_PASTE21, \ | |
2660 NLOHMANN_JSON_PASTE20, \ | |
2661 NLOHMANN_JSON_PASTE19, \ | |
2662 NLOHMANN_JSON_PASTE18, \ | |
2663 NLOHMANN_JSON_PASTE17, \ | |
2664 NLOHMANN_JSON_PASTE16, \ | |
2665 NLOHMANN_JSON_PASTE15, \ | |
2666 NLOHMANN_JSON_PASTE14, \ | |
2667 NLOHMANN_JSON_PASTE13, \ | |
2668 NLOHMANN_JSON_PASTE12, \ | |
2669 NLOHMANN_JSON_PASTE11, \ | |
2670 NLOHMANN_JSON_PASTE10, \ | |
2671 NLOHMANN_JSON_PASTE9, \ | |
2672 NLOHMANN_JSON_PASTE8, \ | |
2673 NLOHMANN_JSON_PASTE7, \ | |
2674 NLOHMANN_JSON_PASTE6, \ | |
2675 NLOHMANN_JSON_PASTE5, \ | |
2676 NLOHMANN_JSON_PASTE4, \ | |
2677 NLOHMANN_JSON_PASTE3, \ | |
2678 NLOHMANN_JSON_PASTE2, \ | |
2679 NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) | |
2680 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) | |
2681 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) | |
2682 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) | |
2683 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) | |
2684 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) | |
2685 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) | |
2686 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) | |
2687 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) | |
2688 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) | |
2689 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) | |
2690 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) | |
2691 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) | |
2692 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) | |
2693 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) | |
2694 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) | |
2695 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) | |
2696 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) | |
2697 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) | |
2698 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) | |
2699 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) | |
2700 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) | |
2701 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) | |
2702 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) | |
2703 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) | |
2704 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) | |
2705 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) | |
2706 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) | |
2707 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) | |
2708 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) | |
2709 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) | |
2710 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) | |
2711 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) | |
2712 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) | |
2713 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) | |
2714 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) | |
2715 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) | |
2716 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) | |
2717 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) | |
2718 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) | |
2719 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) | |
2720 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) | |
2721 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) | |
2722 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) | |
2723 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) | |
2724 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) | |
2725 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) | |
2726 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) | |
2727 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) | |
2728 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) | |
2729 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) | |
2730 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) | |
2731 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) | |
2732 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) | |
2733 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) | |
2734 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) | |
2735 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) | |
2736 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) | |
2737 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) | |
2738 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) | |
2739 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) | |
2740 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) | |
2741 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) | |
2742 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) | |
2743 | |
2744 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; | |
2745 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); | |
2746 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); | |
2747 | |
2748 /*! | |
2749 @brief macro | |
2750 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE | |
2751 @since version 3.9.0 | |
2752 */ | |
2753 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ | |
2754 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | |
2755 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } | |
2756 | |
2757 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ | |
2758 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | |
2759 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } | |
2760 | |
2761 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ | |
2762 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } | |
2763 | |
2764 /*! | |
2765 @brief macro | |
2766 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE | |
2767 @since version 3.9.0 | |
2768 */ | |
2769 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ | |
2770 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | |
2771 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } | |
2772 | |
2773 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ | |
2774 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } | |
2775 | |
2776 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ | |
2777 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ | |
2778 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } | |
2779 | |
2780 // inspired from https://stackoverflow.com/a/26745591 | |
2781 // allows to call any std function as if (e.g. with begin): | |
2782 // using std::begin; begin(x); | |
2783 // | |
2784 // it allows using the detected idiom to retrieve the return type | |
2785 // of such an expression | |
2786 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ | |
2787 namespace detail { \ | |
2788 using std::std_name; \ | |
2789 \ | |
2790 template<typename... T> \ | |
2791 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ | |
2792 } \ | |
2793 \ | |
2794 namespace detail2 { \ | |
2795 struct std_name##_tag \ | |
2796 { \ | |
2797 }; \ | |
2798 \ | |
2799 template<typename... T> \ | |
2800 std_name##_tag std_name(T&&...); \ | |
2801 \ | |
2802 template<typename... T> \ | |
2803 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ | |
2804 \ | |
2805 template<typename... T> \ | |
2806 struct would_call_std_##std_name \ | |
2807 { \ | |
2808 static constexpr auto const value = ::nlohmann::detail:: \ | |
2809 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ | |
2810 }; \ | |
2811 } /* namespace detail2 */ \ | |
2812 \ | |
2813 template<typename... T> \ | |
2814 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \ | |
2815 { \ | |
2816 } | |
2817 | |
2818 #ifndef JSON_USE_IMPLICIT_CONVERSIONS | |
2819 #define JSON_USE_IMPLICIT_CONVERSIONS 1 | |
2820 #endif | |
2821 | |
2822 #if JSON_USE_IMPLICIT_CONVERSIONS | |
2823 #define JSON_EXPLICIT | |
2824 #else | |
2825 #define JSON_EXPLICIT explicit | |
2826 #endif | |
2827 | |
2828 #ifndef JSON_DISABLE_ENUM_SERIALIZATION | |
2829 #define JSON_DISABLE_ENUM_SERIALIZATION 0 | |
2830 #endif | |
2831 | |
2832 #ifndef JSON_USE_GLOBAL_UDLS | |
2833 #define JSON_USE_GLOBAL_UDLS 1 | |
2834 #endif | |
2835 | |
2836 #if JSON_HAS_THREE_WAY_COMPARISON | |
2837 #include <compare> // partial_ordering | |
2838 #endif | |
2839 | |
2840 NLOHMANN_JSON_NAMESPACE_BEGIN | |
2841 namespace detail | |
2842 { | |
2843 | |
2844 /////////////////////////// | |
2845 // JSON type enumeration // | |
2846 /////////////////////////// | |
2847 | |
2848 /*! | |
2849 @brief the JSON type enumeration | |
2850 | |
2851 This enumeration collects the different JSON types. It is internally used to | |
2852 distinguish the stored values, and the functions @ref basic_json::is_null(), | |
2853 @ref basic_json::is_object(), @ref basic_json::is_array(), | |
2854 @ref basic_json::is_string(), @ref basic_json::is_boolean(), | |
2855 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), | |
2856 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), | |
2857 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and | |
2858 @ref basic_json::is_structured() rely on it. | |
2859 | |
2860 @note There are three enumeration entries (number_integer, number_unsigned, and | |
2861 number_float), because the library distinguishes these three types for numbers: | |
2862 @ref basic_json::number_unsigned_t is used for unsigned integers, | |
2863 @ref basic_json::number_integer_t is used for signed integers, and | |
2864 @ref basic_json::number_float_t is used for floating-point numbers or to | |
2865 approximate integers which do not fit in the limits of their respective type. | |
2866 | |
2867 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON | |
2868 value with the default value for a given type | |
2869 | |
2870 @since version 1.0.0 | |
2871 */ | |
2872 enum class value_t : std::uint8_t | |
2873 { | |
2874 null, ///< null value | |
2875 object, ///< object (unordered set of name/value pairs) | |
2876 array, ///< array (ordered collection of values) | |
2877 string, ///< string value | |
2878 boolean, ///< boolean value | |
2879 number_integer, ///< number value (signed integer) | |
2880 number_unsigned, ///< number value (unsigned integer) | |
2881 number_float, ///< number value (floating-point) | |
2882 binary, ///< binary array (ordered collection of bytes) | |
2883 discarded ///< discarded by the parser callback function | |
2884 }; | |
2885 | |
2886 /*! | |
2887 @brief comparison operator for JSON types | |
2888 | |
2889 Returns an ordering that is similar to Python: | |
2890 - order: null < boolean < number < object < array < string < binary | |
2891 - furthermore, each type is not smaller than itself | |
2892 - discarded values are not comparable | |
2893 - binary is represented as a b"" string in python and directly comparable to a | |
2894 string; however, making a binary array directly comparable with a string would | |
2895 be surprising behavior in a JSON file. | |
2896 | |
2897 @since version 1.0.0 | |
2898 */ | |
2899 #if JSON_HAS_THREE_WAY_COMPARISON | |
2900 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* | |
2901 #else | |
2902 inline bool operator<(const value_t lhs, const value_t rhs) noexcept | |
2903 #endif | |
2904 { | |
2905 static constexpr std::array<std::uint8_t, 9> order = {{ | |
2906 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, | |
2907 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, | |
2908 6 /* binary */ | |
2909 } | |
2910 }; | |
2911 | |
2912 const auto l_index = static_cast<std::size_t>(lhs); | |
2913 const auto r_index = static_cast<std::size_t>(rhs); | |
2914 #if JSON_HAS_THREE_WAY_COMPARISON | |
2915 if (l_index < order.size() && r_index < order.size()) | |
2916 { | |
2917 return order[l_index] <=> order[r_index]; // *NOPAD* | |
2918 } | |
2919 return std::partial_ordering::unordered; | |
2920 #else | |
2921 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; | |
2922 #endif | |
2923 } | |
2924 | |
2925 // GCC selects the built-in operator< over an operator rewritten from | |
2926 // a user-defined spaceship operator | |
2927 // Clang, MSVC, and ICC select the rewritten candidate | |
2928 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) | |
2929 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) | |
2930 inline bool operator<(const value_t lhs, const value_t rhs) noexcept | |
2931 { | |
2932 return std::is_lt(lhs <=> rhs); // *NOPAD* | |
2933 } | |
2934 #endif | |
2935 | |
2936 } // namespace detail | |
2937 NLOHMANN_JSON_NAMESPACE_END | |
2938 | |
2939 // #include <nlohmann/detail/string_escape.hpp> | |
2940 // __ _____ _____ _____ | |
2941 // __| | __| | | | JSON for Modern C++ | |
2942 // | | |__ | | | | | | version 3.11.3 | |
2943 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
2944 // | |
2945 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
2946 // SPDX-License-Identifier: MIT | |
2947 | |
2948 | |
2949 | |
2950 // #include <nlohmann/detail/abi_macros.hpp> | |
2951 | |
2952 | |
2953 NLOHMANN_JSON_NAMESPACE_BEGIN | |
2954 namespace detail | |
2955 { | |
2956 | |
2957 /*! | |
2958 @brief replace all occurrences of a substring by another string | |
2959 | |
2960 @param[in,out] s the string to manipulate; changed so that all | |
2961 occurrences of @a f are replaced with @a t | |
2962 @param[in] f the substring to replace with @a t | |
2963 @param[in] t the string to replace @a f | |
2964 | |
2965 @pre The search string @a f must not be empty. **This precondition is | |
2966 enforced with an assertion.** | |
2967 | |
2968 @since version 2.0.0 | |
2969 */ | |
2970 template<typename StringType> | |
2971 inline void replace_substring(StringType& s, const StringType& f, | |
2972 const StringType& t) | |
2973 { | |
2974 JSON_ASSERT(!f.empty()); | |
2975 for (auto pos = s.find(f); // find first occurrence of f | |
2976 pos != StringType::npos; // make sure f was found | |
2977 s.replace(pos, f.size(), t), // replace with t, and | |
2978 pos = s.find(f, pos + t.size())) // find next occurrence of f | |
2979 {} | |
2980 } | |
2981 | |
2982 /*! | |
2983 * @brief string escaping as described in RFC 6901 (Sect. 4) | |
2984 * @param[in] s string to escape | |
2985 * @return escaped string | |
2986 * | |
2987 * Note the order of escaping "~" to "~0" and "/" to "~1" is important. | |
2988 */ | |
2989 template<typename StringType> | |
2990 inline StringType escape(StringType s) | |
2991 { | |
2992 replace_substring(s, StringType{"~"}, StringType{"~0"}); | |
2993 replace_substring(s, StringType{"/"}, StringType{"~1"}); | |
2994 return s; | |
2995 } | |
2996 | |
2997 /*! | |
2998 * @brief string unescaping as described in RFC 6901 (Sect. 4) | |
2999 * @param[in] s string to unescape | |
3000 * @return unescaped string | |
3001 * | |
3002 * Note the order of escaping "~1" to "/" and "~0" to "~" is important. | |
3003 */ | |
3004 template<typename StringType> | |
3005 static void unescape(StringType& s) | |
3006 { | |
3007 replace_substring(s, StringType{"~1"}, StringType{"/"}); | |
3008 replace_substring(s, StringType{"~0"}, StringType{"~"}); | |
3009 } | |
3010 | |
3011 } // namespace detail | |
3012 NLOHMANN_JSON_NAMESPACE_END | |
3013 | |
3014 // #include <nlohmann/detail/input/position_t.hpp> | |
3015 // __ _____ _____ _____ | |
3016 // __| | __| | | | JSON for Modern C++ | |
3017 // | | |__ | | | | | | version 3.11.3 | |
3018 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3019 // | |
3020 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3021 // SPDX-License-Identifier: MIT | |
3022 | |
3023 | |
3024 | |
3025 #include <cstddef> // size_t | |
3026 | |
3027 // #include <nlohmann/detail/abi_macros.hpp> | |
3028 | |
3029 | |
3030 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3031 namespace detail | |
3032 { | |
3033 | |
3034 /// struct to capture the start position of the current token | |
3035 struct position_t | |
3036 { | |
3037 /// the total number of characters read | |
3038 std::size_t chars_read_total = 0; | |
3039 /// the number of characters read in the current line | |
3040 std::size_t chars_read_current_line = 0; | |
3041 /// the number of lines read | |
3042 std::size_t lines_read = 0; | |
3043 | |
3044 /// conversion to size_t to preserve SAX interface | |
3045 constexpr operator size_t() const | |
3046 { | |
3047 return chars_read_total; | |
3048 } | |
3049 }; | |
3050 | |
3051 } // namespace detail | |
3052 NLOHMANN_JSON_NAMESPACE_END | |
3053 | |
3054 // #include <nlohmann/detail/macro_scope.hpp> | |
3055 | |
3056 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
3057 // __ _____ _____ _____ | |
3058 // __| | __| | | | JSON for Modern C++ | |
3059 // | | |__ | | | | | | version 3.11.3 | |
3060 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3061 // | |
3062 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3063 // SPDX-FileCopyrightText: 2018 The Abseil Authors | |
3064 // SPDX-License-Identifier: MIT | |
3065 | |
3066 | |
3067 | |
3068 #include <array> // array | |
3069 #include <cstddef> // size_t | |
3070 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type | |
3071 #include <utility> // index_sequence, make_index_sequence, index_sequence_for | |
3072 | |
3073 // #include <nlohmann/detail/macro_scope.hpp> | |
3074 | |
3075 | |
3076 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3077 namespace detail | |
3078 { | |
3079 | |
3080 template<typename T> | |
3081 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; | |
3082 | |
3083 #ifdef JSON_HAS_CPP_14 | |
3084 | |
3085 // the following utilities are natively available in C++14 | |
3086 using std::enable_if_t; | |
3087 using std::index_sequence; | |
3088 using std::make_index_sequence; | |
3089 using std::index_sequence_for; | |
3090 | |
3091 #else | |
3092 | |
3093 // alias templates to reduce boilerplate | |
3094 template<bool B, typename T = void> | |
3095 using enable_if_t = typename std::enable_if<B, T>::type; | |
3096 | |
3097 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h | |
3098 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. | |
3099 | |
3100 //// START OF CODE FROM GOOGLE ABSEIL | |
3101 | |
3102 // integer_sequence | |
3103 // | |
3104 // Class template representing a compile-time integer sequence. An instantiation | |
3105 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its | |
3106 // type through its template arguments (which is a common need when | |
3107 // working with C++11 variadic templates). `absl::integer_sequence` is designed | |
3108 // to be a drop-in replacement for C++14's `std::integer_sequence`. | |
3109 // | |
3110 // Example: | |
3111 // | |
3112 // template< class T, T... Ints > | |
3113 // void user_function(integer_sequence<T, Ints...>); | |
3114 // | |
3115 // int main() | |
3116 // { | |
3117 // // user_function's `T` will be deduced to `int` and `Ints...` | |
3118 // // will be deduced to `0, 1, 2, 3, 4`. | |
3119 // user_function(make_integer_sequence<int, 5>()); | |
3120 // } | |
3121 template <typename T, T... Ints> | |
3122 struct integer_sequence | |
3123 { | |
3124 using value_type = T; | |
3125 static constexpr std::size_t size() noexcept | |
3126 { | |
3127 return sizeof...(Ints); | |
3128 } | |
3129 }; | |
3130 | |
3131 // index_sequence | |
3132 // | |
3133 // A helper template for an `integer_sequence` of `size_t`, | |
3134 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's | |
3135 // `std::index_sequence`. | |
3136 template <size_t... Ints> | |
3137 using index_sequence = integer_sequence<size_t, Ints...>; | |
3138 | |
3139 namespace utility_internal | |
3140 { | |
3141 | |
3142 template <typename Seq, size_t SeqSize, size_t Rem> | |
3143 struct Extend; | |
3144 | |
3145 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. | |
3146 template <typename T, T... Ints, size_t SeqSize> | |
3147 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> | |
3148 { | |
3149 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; | |
3150 }; | |
3151 | |
3152 template <typename T, T... Ints, size_t SeqSize> | |
3153 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> | |
3154 { | |
3155 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; | |
3156 }; | |
3157 | |
3158 // Recursion helper for 'make_integer_sequence<T, N>'. | |
3159 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. | |
3160 template <typename T, size_t N> | |
3161 struct Gen | |
3162 { | |
3163 using type = | |
3164 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; | |
3165 }; | |
3166 | |
3167 template <typename T> | |
3168 struct Gen<T, 0> | |
3169 { | |
3170 using type = integer_sequence<T>; | |
3171 }; | |
3172 | |
3173 } // namespace utility_internal | |
3174 | |
3175 // Compile-time sequences of integers | |
3176 | |
3177 // make_integer_sequence | |
3178 // | |
3179 // This template alias is equivalent to | |
3180 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in | |
3181 // replacement for C++14's `std::make_integer_sequence`. | |
3182 template <typename T, T N> | |
3183 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; | |
3184 | |
3185 // make_index_sequence | |
3186 // | |
3187 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, | |
3188 // and is designed to be a drop-in replacement for C++14's | |
3189 // `std::make_index_sequence`. | |
3190 template <size_t N> | |
3191 using make_index_sequence = make_integer_sequence<size_t, N>; | |
3192 | |
3193 // index_sequence_for | |
3194 // | |
3195 // Converts a typename pack into an index sequence of the same length, and | |
3196 // is designed to be a drop-in replacement for C++14's | |
3197 // `std::index_sequence_for()` | |
3198 template <typename... Ts> | |
3199 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; | |
3200 | |
3201 //// END OF CODE FROM GOOGLE ABSEIL | |
3202 | |
3203 #endif | |
3204 | |
3205 // dispatch utility (taken from ranges-v3) | |
3206 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; | |
3207 template<> struct priority_tag<0> {}; | |
3208 | |
3209 // taken from ranges-v3 | |
3210 template<typename T> | |
3211 struct static_const | |
3212 { | |
3213 static JSON_INLINE_VARIABLE constexpr T value{}; | |
3214 }; | |
3215 | |
3216 #ifndef JSON_HAS_CPP_17 | |
3217 template<typename T> | |
3218 constexpr T static_const<T>::value; | |
3219 #endif | |
3220 | |
3221 template<typename T, typename... Args> | |
3222 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) | |
3223 { | |
3224 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; | |
3225 } | |
3226 | |
3227 } // namespace detail | |
3228 NLOHMANN_JSON_NAMESPACE_END | |
3229 | |
3230 // #include <nlohmann/detail/meta/type_traits.hpp> | |
3231 // __ _____ _____ _____ | |
3232 // __| | __| | | | JSON for Modern C++ | |
3233 // | | |__ | | | | | | version 3.11.3 | |
3234 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3235 // | |
3236 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3237 // SPDX-License-Identifier: MIT | |
3238 | |
3239 | |
3240 | |
3241 #include <limits> // numeric_limits | |
3242 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type | |
3243 #include <utility> // declval | |
3244 #include <tuple> // tuple | |
3245 #include <string> // char_traits | |
3246 | |
3247 // #include <nlohmann/detail/iterators/iterator_traits.hpp> | |
3248 // __ _____ _____ _____ | |
3249 // __| | __| | | | JSON for Modern C++ | |
3250 // | | |__ | | | | | | version 3.11.3 | |
3251 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3252 // | |
3253 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3254 // SPDX-License-Identifier: MIT | |
3255 | |
3256 | |
3257 | |
3258 #include <iterator> // random_access_iterator_tag | |
3259 | |
3260 // #include <nlohmann/detail/abi_macros.hpp> | |
3261 | |
3262 // #include <nlohmann/detail/meta/void_t.hpp> | |
3263 | |
3264 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
3265 | |
3266 | |
3267 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3268 namespace detail | |
3269 { | |
3270 | |
3271 template<typename It, typename = void> | |
3272 struct iterator_types {}; | |
3273 | |
3274 template<typename It> | |
3275 struct iterator_types < | |
3276 It, | |
3277 void_t<typename It::difference_type, typename It::value_type, typename It::pointer, | |
3278 typename It::reference, typename It::iterator_category >> | |
3279 { | |
3280 using difference_type = typename It::difference_type; | |
3281 using value_type = typename It::value_type; | |
3282 using pointer = typename It::pointer; | |
3283 using reference = typename It::reference; | |
3284 using iterator_category = typename It::iterator_category; | |
3285 }; | |
3286 | |
3287 // This is required as some compilers implement std::iterator_traits in a way that | |
3288 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. | |
3289 template<typename T, typename = void> | |
3290 struct iterator_traits | |
3291 { | |
3292 }; | |
3293 | |
3294 template<typename T> | |
3295 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >> | |
3296 : iterator_types<T> | |
3297 { | |
3298 }; | |
3299 | |
3300 template<typename T> | |
3301 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> | |
3302 { | |
3303 using iterator_category = std::random_access_iterator_tag; | |
3304 using value_type = T; | |
3305 using difference_type = ptrdiff_t; | |
3306 using pointer = T*; | |
3307 using reference = T&; | |
3308 }; | |
3309 | |
3310 } // namespace detail | |
3311 NLOHMANN_JSON_NAMESPACE_END | |
3312 | |
3313 // #include <nlohmann/detail/macro_scope.hpp> | |
3314 | |
3315 // #include <nlohmann/detail/meta/call_std/begin.hpp> | |
3316 // __ _____ _____ _____ | |
3317 // __| | __| | | | JSON for Modern C++ | |
3318 // | | |__ | | | | | | version 3.11.3 | |
3319 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3320 // | |
3321 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3322 // SPDX-License-Identifier: MIT | |
3323 | |
3324 | |
3325 | |
3326 // #include <nlohmann/detail/macro_scope.hpp> | |
3327 | |
3328 | |
3329 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3330 | |
3331 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); | |
3332 | |
3333 NLOHMANN_JSON_NAMESPACE_END | |
3334 | |
3335 // #include <nlohmann/detail/meta/call_std/end.hpp> | |
3336 // __ _____ _____ _____ | |
3337 // __| | __| | | | JSON for Modern C++ | |
3338 // | | |__ | | | | | | version 3.11.3 | |
3339 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3340 // | |
3341 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3342 // SPDX-License-Identifier: MIT | |
3343 | |
3344 | |
3345 | |
3346 // #include <nlohmann/detail/macro_scope.hpp> | |
3347 | |
3348 | |
3349 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3350 | |
3351 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); | |
3352 | |
3353 NLOHMANN_JSON_NAMESPACE_END | |
3354 | |
3355 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
3356 | |
3357 // #include <nlohmann/detail/meta/detected.hpp> | |
3358 | |
3359 // #include <nlohmann/json_fwd.hpp> | |
3360 // __ _____ _____ _____ | |
3361 // __| | __| | | | JSON for Modern C++ | |
3362 // | | |__ | | | | | | version 3.11.3 | |
3363 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
3364 // | |
3365 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
3366 // SPDX-License-Identifier: MIT | |
3367 | |
3368 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ | |
3369 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ | |
3370 | |
3371 #include <cstdint> // int64_t, uint64_t | |
3372 #include <map> // map | |
3373 #include <memory> // allocator | |
3374 #include <string> // string | |
3375 #include <vector> // vector | |
3376 | |
3377 // #include <nlohmann/detail/abi_macros.hpp> | |
3378 | |
3379 | |
3380 /*! | |
3381 @brief namespace for Niels Lohmann | |
3382 @see https://github.com/nlohmann | |
3383 @since version 1.0.0 | |
3384 */ | |
3385 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3386 | |
3387 /*! | |
3388 @brief default JSONSerializer template argument | |
3389 | |
3390 This serializer ignores the template arguments and uses ADL | |
3391 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) | |
3392 for serialization. | |
3393 */ | |
3394 template<typename T = void, typename SFINAE = void> | |
3395 struct adl_serializer; | |
3396 | |
3397 /// a class to store JSON values | |
3398 /// @sa https://json.nlohmann.me/api/basic_json/ | |
3399 template<template<typename U, typename V, typename... Args> class ObjectType = | |
3400 std::map, | |
3401 template<typename U, typename... Args> class ArrayType = std::vector, | |
3402 class StringType = std::string, class BooleanType = bool, | |
3403 class NumberIntegerType = std::int64_t, | |
3404 class NumberUnsignedType = std::uint64_t, | |
3405 class NumberFloatType = double, | |
3406 template<typename U> class AllocatorType = std::allocator, | |
3407 template<typename T, typename SFINAE = void> class JSONSerializer = | |
3408 adl_serializer, | |
3409 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError | |
3410 class CustomBaseClass = void> | |
3411 class basic_json; | |
3412 | |
3413 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document | |
3414 /// @sa https://json.nlohmann.me/api/json_pointer/ | |
3415 template<typename RefStringType> | |
3416 class json_pointer; | |
3417 | |
3418 /*! | |
3419 @brief default specialization | |
3420 @sa https://json.nlohmann.me/api/json/ | |
3421 */ | |
3422 using json = basic_json<>; | |
3423 | |
3424 /// @brief a minimal map-like container that preserves insertion order | |
3425 /// @sa https://json.nlohmann.me/api/ordered_map/ | |
3426 template<class Key, class T, class IgnoredLess, class Allocator> | |
3427 struct ordered_map; | |
3428 | |
3429 /// @brief specialization that maintains the insertion order of object keys | |
3430 /// @sa https://json.nlohmann.me/api/ordered_json/ | |
3431 using ordered_json = basic_json<nlohmann::ordered_map>; | |
3432 | |
3433 NLOHMANN_JSON_NAMESPACE_END | |
3434 | |
3435 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ | |
3436 | |
3437 | |
3438 NLOHMANN_JSON_NAMESPACE_BEGIN | |
3439 /*! | |
3440 @brief detail namespace with internal helper functions | |
3441 | |
3442 This namespace collects functions that should not be exposed, | |
3443 implementations of some @ref basic_json methods, and meta-programming helpers. | |
3444 | |
3445 @since version 2.1.0 | |
3446 */ | |
3447 namespace detail | |
3448 { | |
3449 | |
3450 ///////////// | |
3451 // helpers // | |
3452 ///////////// | |
3453 | |
3454 // Note to maintainers: | |
3455 // | |
3456 // Every trait in this file expects a non CV-qualified type. | |
3457 // The only exceptions are in the 'aliases for detected' section | |
3458 // (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) | |
3459 // | |
3460 // In this case, T has to be properly CV-qualified to constraint the function arguments | |
3461 // (e.g. to_json(BasicJsonType&, const T&)) | |
3462 | |
3463 template<typename> struct is_basic_json : std::false_type {}; | |
3464 | |
3465 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
3466 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; | |
3467 | |
3468 // used by exceptions create() member functions | |
3469 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t | |
3470 // false_type otherwise | |
3471 template<typename BasicJsonContext> | |
3472 struct is_basic_json_context : | |
3473 std::integral_constant < bool, | |
3474 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value | |
3475 || std::is_same<BasicJsonContext, std::nullptr_t>::value > | |
3476 {}; | |
3477 | |
3478 ////////////////////// | |
3479 // json_ref helpers // | |
3480 ////////////////////// | |
3481 | |
3482 template<typename> | |
3483 class json_ref; | |
3484 | |
3485 template<typename> | |
3486 struct is_json_ref : std::false_type {}; | |
3487 | |
3488 template<typename T> | |
3489 struct is_json_ref<json_ref<T>> : std::true_type {}; | |
3490 | |
3491 ////////////////////////// | |
3492 // aliases for detected // | |
3493 ////////////////////////// | |
3494 | |
3495 template<typename T> | |
3496 using mapped_type_t = typename T::mapped_type; | |
3497 | |
3498 template<typename T> | |
3499 using key_type_t = typename T::key_type; | |
3500 | |
3501 template<typename T> | |
3502 using value_type_t = typename T::value_type; | |
3503 | |
3504 template<typename T> | |
3505 using difference_type_t = typename T::difference_type; | |
3506 | |
3507 template<typename T> | |
3508 using pointer_t = typename T::pointer; | |
3509 | |
3510 template<typename T> | |
3511 using reference_t = typename T::reference; | |
3512 | |
3513 template<typename T> | |
3514 using iterator_category_t = typename T::iterator_category; | |
3515 | |
3516 template<typename T, typename... Args> | |
3517 using to_json_function = decltype(T::to_json(std::declval<Args>()...)); | |
3518 | |
3519 template<typename T, typename... Args> | |
3520 using from_json_function = decltype(T::from_json(std::declval<Args>()...)); | |
3521 | |
3522 template<typename T, typename U> | |
3523 using get_template_function = decltype(std::declval<T>().template get<U>()); | |
3524 | |
3525 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists | |
3526 template<typename BasicJsonType, typename T, typename = void> | |
3527 struct has_from_json : std::false_type {}; | |
3528 | |
3529 // trait checking if j.get<T> is valid | |
3530 // use this trait instead of std::is_constructible or std::is_convertible, | |
3531 // both rely on, or make use of implicit conversions, and thus fail when T | |
3532 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) | |
3533 template <typename BasicJsonType, typename T> | |
3534 struct is_getable | |
3535 { | |
3536 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value; | |
3537 }; | |
3538 | |
3539 template<typename BasicJsonType, typename T> | |
3540 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | |
3541 { | |
3542 using serializer = typename BasicJsonType::template json_serializer<T, void>; | |
3543 | |
3544 static constexpr bool value = | |
3545 is_detected_exact<void, from_json_function, serializer, | |
3546 const BasicJsonType&, T&>::value; | |
3547 }; | |
3548 | |
3549 // This trait checks if JSONSerializer<T>::from_json(json const&) exists | |
3550 // this overload is used for non-default-constructible user-defined-types | |
3551 template<typename BasicJsonType, typename T, typename = void> | |
3552 struct has_non_default_from_json : std::false_type {}; | |
3553 | |
3554 template<typename BasicJsonType, typename T> | |
3555 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | |
3556 { | |
3557 using serializer = typename BasicJsonType::template json_serializer<T, void>; | |
3558 | |
3559 static constexpr bool value = | |
3560 is_detected_exact<T, from_json_function, serializer, | |
3561 const BasicJsonType&>::value; | |
3562 }; | |
3563 | |
3564 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists | |
3565 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. | |
3566 template<typename BasicJsonType, typename T, typename = void> | |
3567 struct has_to_json : std::false_type {}; | |
3568 | |
3569 template<typename BasicJsonType, typename T> | |
3570 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> | |
3571 { | |
3572 using serializer = typename BasicJsonType::template json_serializer<T, void>; | |
3573 | |
3574 static constexpr bool value = | |
3575 is_detected_exact<void, to_json_function, serializer, BasicJsonType&, | |
3576 T>::value; | |
3577 }; | |
3578 | |
3579 template<typename T> | |
3580 using detect_key_compare = typename T::key_compare; | |
3581 | |
3582 template<typename T> | |
3583 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {}; | |
3584 | |
3585 // obtains the actual object key comparator | |
3586 template<typename BasicJsonType> | |
3587 struct actual_object_comparator | |
3588 { | |
3589 using object_t = typename BasicJsonType::object_t; | |
3590 using object_comparator_t = typename BasicJsonType::default_object_comparator_t; | |
3591 using type = typename std::conditional < has_key_compare<object_t>::value, | |
3592 typename object_t::key_compare, object_comparator_t>::type; | |
3593 }; | |
3594 | |
3595 template<typename BasicJsonType> | |
3596 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type; | |
3597 | |
3598 ///////////////// | |
3599 // char_traits // | |
3600 ///////////////// | |
3601 | |
3602 // Primary template of char_traits calls std char_traits | |
3603 template<typename T> | |
3604 struct char_traits : std::char_traits<T> | |
3605 {}; | |
3606 | |
3607 // Explicitly define char traits for unsigned char since it is not standard | |
3608 template<> | |
3609 struct char_traits<unsigned char> : std::char_traits<char> | |
3610 { | |
3611 using char_type = unsigned char; | |
3612 using int_type = uint64_t; | |
3613 | |
3614 // Redefine to_int_type function | |
3615 static int_type to_int_type(char_type c) noexcept | |
3616 { | |
3617 return static_cast<int_type>(c); | |
3618 } | |
3619 | |
3620 static char_type to_char_type(int_type i) noexcept | |
3621 { | |
3622 return static_cast<char_type>(i); | |
3623 } | |
3624 | |
3625 static constexpr int_type eof() noexcept | |
3626 { | |
3627 return static_cast<int_type>(EOF); | |
3628 } | |
3629 }; | |
3630 | |
3631 // Explicitly define char traits for signed char since it is not standard | |
3632 template<> | |
3633 struct char_traits<signed char> : std::char_traits<char> | |
3634 { | |
3635 using char_type = signed char; | |
3636 using int_type = uint64_t; | |
3637 | |
3638 // Redefine to_int_type function | |
3639 static int_type to_int_type(char_type c) noexcept | |
3640 { | |
3641 return static_cast<int_type>(c); | |
3642 } | |
3643 | |
3644 static char_type to_char_type(int_type i) noexcept | |
3645 { | |
3646 return static_cast<char_type>(i); | |
3647 } | |
3648 | |
3649 static constexpr int_type eof() noexcept | |
3650 { | |
3651 return static_cast<int_type>(EOF); | |
3652 } | |
3653 }; | |
3654 | |
3655 /////////////////// | |
3656 // is_ functions // | |
3657 /////////////////// | |
3658 | |
3659 // https://en.cppreference.com/w/cpp/types/conjunction | |
3660 template<class...> struct conjunction : std::true_type { }; | |
3661 template<class B> struct conjunction<B> : B { }; | |
3662 template<class B, class... Bn> | |
3663 struct conjunction<B, Bn...> | |
3664 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {}; | |
3665 | |
3666 // https://en.cppreference.com/w/cpp/types/negation | |
3667 template<class B> struct negation : std::integral_constant < bool, !B::value > { }; | |
3668 | |
3669 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for | |
3670 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). | |
3671 // This causes compile errors in e.g. clang 3.5 or gcc 4.9. | |
3672 template <typename T> | |
3673 struct is_default_constructible : std::is_default_constructible<T> {}; | |
3674 | |
3675 template <typename T1, typename T2> | |
3676 struct is_default_constructible<std::pair<T1, T2>> | |
3677 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; | |
3678 | |
3679 template <typename T1, typename T2> | |
3680 struct is_default_constructible<const std::pair<T1, T2>> | |
3681 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; | |
3682 | |
3683 template <typename... Ts> | |
3684 struct is_default_constructible<std::tuple<Ts...>> | |
3685 : conjunction<is_default_constructible<Ts>...> {}; | |
3686 | |
3687 template <typename... Ts> | |
3688 struct is_default_constructible<const std::tuple<Ts...>> | |
3689 : conjunction<is_default_constructible<Ts>...> {}; | |
3690 | |
3691 template <typename T, typename... Args> | |
3692 struct is_constructible : std::is_constructible<T, Args...> {}; | |
3693 | |
3694 template <typename T1, typename T2> | |
3695 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {}; | |
3696 | |
3697 template <typename T1, typename T2> | |
3698 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {}; | |
3699 | |
3700 template <typename... Ts> | |
3701 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {}; | |
3702 | |
3703 template <typename... Ts> | |
3704 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {}; | |
3705 | |
3706 template<typename T, typename = void> | |
3707 struct is_iterator_traits : std::false_type {}; | |
3708 | |
3709 template<typename T> | |
3710 struct is_iterator_traits<iterator_traits<T>> | |
3711 { | |
3712 private: | |
3713 using traits = iterator_traits<T>; | |
3714 | |
3715 public: | |
3716 static constexpr auto value = | |
3717 is_detected<value_type_t, traits>::value && | |
3718 is_detected<difference_type_t, traits>::value && | |
3719 is_detected<pointer_t, traits>::value && | |
3720 is_detected<iterator_category_t, traits>::value && | |
3721 is_detected<reference_t, traits>::value; | |
3722 }; | |
3723 | |
3724 template<typename T> | |
3725 struct is_range | |
3726 { | |
3727 private: | |
3728 using t_ref = typename std::add_lvalue_reference<T>::type; | |
3729 | |
3730 using iterator = detected_t<result_of_begin, t_ref>; | |
3731 using sentinel = detected_t<result_of_end, t_ref>; | |
3732 | |
3733 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator | |
3734 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for | |
3735 // but reimplementing these would be too much work, as a lot of other concepts are used underneath | |
3736 static constexpr auto is_iterator_begin = | |
3737 is_iterator_traits<iterator_traits<iterator>>::value; | |
3738 | |
3739 public: | |
3740 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin; | |
3741 }; | |
3742 | |
3743 template<typename R> | |
3744 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>; | |
3745 | |
3746 template<typename T> | |
3747 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>; | |
3748 | |
3749 // The following implementation of is_complete_type is taken from | |
3750 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ | |
3751 // and is written by Xiang Fan who agreed to using it in this library. | |
3752 | |
3753 template<typename T, typename = void> | |
3754 struct is_complete_type : std::false_type {}; | |
3755 | |
3756 template<typename T> | |
3757 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; | |
3758 | |
3759 template<typename BasicJsonType, typename CompatibleObjectType, | |
3760 typename = void> | |
3761 struct is_compatible_object_type_impl : std::false_type {}; | |
3762 | |
3763 template<typename BasicJsonType, typename CompatibleObjectType> | |
3764 struct is_compatible_object_type_impl < | |
3765 BasicJsonType, CompatibleObjectType, | |
3766 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&& | |
3767 is_detected<key_type_t, CompatibleObjectType>::value >> | |
3768 { | |
3769 using object_t = typename BasicJsonType::object_t; | |
3770 | |
3771 // macOS's is_constructible does not play well with nonesuch... | |
3772 static constexpr bool value = | |
3773 is_constructible<typename object_t::key_type, | |
3774 typename CompatibleObjectType::key_type>::value && | |
3775 is_constructible<typename object_t::mapped_type, | |
3776 typename CompatibleObjectType::mapped_type>::value; | |
3777 }; | |
3778 | |
3779 template<typename BasicJsonType, typename CompatibleObjectType> | |
3780 struct is_compatible_object_type | |
3781 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {}; | |
3782 | |
3783 template<typename BasicJsonType, typename ConstructibleObjectType, | |
3784 typename = void> | |
3785 struct is_constructible_object_type_impl : std::false_type {}; | |
3786 | |
3787 template<typename BasicJsonType, typename ConstructibleObjectType> | |
3788 struct is_constructible_object_type_impl < | |
3789 BasicJsonType, ConstructibleObjectType, | |
3790 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&& | |
3791 is_detected<key_type_t, ConstructibleObjectType>::value >> | |
3792 { | |
3793 using object_t = typename BasicJsonType::object_t; | |
3794 | |
3795 static constexpr bool value = | |
3796 (is_default_constructible<ConstructibleObjectType>::value && | |
3797 (std::is_move_assignable<ConstructibleObjectType>::value || | |
3798 std::is_copy_assignable<ConstructibleObjectType>::value) && | |
3799 (is_constructible<typename ConstructibleObjectType::key_type, | |
3800 typename object_t::key_type>::value && | |
3801 std::is_same < | |
3802 typename object_t::mapped_type, | |
3803 typename ConstructibleObjectType::mapped_type >::value)) || | |
3804 (has_from_json<BasicJsonType, | |
3805 typename ConstructibleObjectType::mapped_type>::value || | |
3806 has_non_default_from_json < | |
3807 BasicJsonType, | |
3808 typename ConstructibleObjectType::mapped_type >::value); | |
3809 }; | |
3810 | |
3811 template<typename BasicJsonType, typename ConstructibleObjectType> | |
3812 struct is_constructible_object_type | |
3813 : is_constructible_object_type_impl<BasicJsonType, | |
3814 ConstructibleObjectType> {}; | |
3815 | |
3816 template<typename BasicJsonType, typename CompatibleStringType> | |
3817 struct is_compatible_string_type | |
3818 { | |
3819 static constexpr auto value = | |
3820 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; | |
3821 }; | |
3822 | |
3823 template<typename BasicJsonType, typename ConstructibleStringType> | |
3824 struct is_constructible_string_type | |
3825 { | |
3826 // launder type through decltype() to fix compilation failure on ICPC | |
3827 #ifdef __INTEL_COMPILER | |
3828 using laundered_type = decltype(std::declval<ConstructibleStringType>()); | |
3829 #else | |
3830 using laundered_type = ConstructibleStringType; | |
3831 #endif | |
3832 | |
3833 static constexpr auto value = | |
3834 conjunction < | |
3835 is_constructible<laundered_type, typename BasicJsonType::string_t>, | |
3836 is_detected_exact<typename BasicJsonType::string_t::value_type, | |
3837 value_type_t, laundered_type >>::value; | |
3838 }; | |
3839 | |
3840 template<typename BasicJsonType, typename CompatibleArrayType, typename = void> | |
3841 struct is_compatible_array_type_impl : std::false_type {}; | |
3842 | |
3843 template<typename BasicJsonType, typename CompatibleArrayType> | |
3844 struct is_compatible_array_type_impl < | |
3845 BasicJsonType, CompatibleArrayType, | |
3846 enable_if_t < | |
3847 is_detected<iterator_t, CompatibleArrayType>::value&& | |
3848 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&& | |
3849 // special case for types like std::filesystem::path whose iterator's value_type are themselves | |
3850 // c.f. https://github.com/nlohmann/json/pull/3073 | |
3851 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >> | |
3852 { | |
3853 static constexpr bool value = | |
3854 is_constructible<BasicJsonType, | |
3855 range_value_t<CompatibleArrayType>>::value; | |
3856 }; | |
3857 | |
3858 template<typename BasicJsonType, typename CompatibleArrayType> | |
3859 struct is_compatible_array_type | |
3860 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {}; | |
3861 | |
3862 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void> | |
3863 struct is_constructible_array_type_impl : std::false_type {}; | |
3864 | |
3865 template<typename BasicJsonType, typename ConstructibleArrayType> | |
3866 struct is_constructible_array_type_impl < | |
3867 BasicJsonType, ConstructibleArrayType, | |
3868 enable_if_t<std::is_same<ConstructibleArrayType, | |
3869 typename BasicJsonType::value_type>::value >> | |
3870 : std::true_type {}; | |
3871 | |
3872 template<typename BasicJsonType, typename ConstructibleArrayType> | |
3873 struct is_constructible_array_type_impl < | |
3874 BasicJsonType, ConstructibleArrayType, | |
3875 enable_if_t < !std::is_same<ConstructibleArrayType, | |
3876 typename BasicJsonType::value_type>::value&& | |
3877 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&& | |
3878 is_default_constructible<ConstructibleArrayType>::value&& | |
3879 (std::is_move_assignable<ConstructibleArrayType>::value || | |
3880 std::is_copy_assignable<ConstructibleArrayType>::value)&& | |
3881 is_detected<iterator_t, ConstructibleArrayType>::value&& | |
3882 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& | |
3883 is_detected<range_value_t, ConstructibleArrayType>::value&& | |
3884 // special case for types like std::filesystem::path whose iterator's value_type are themselves | |
3885 // c.f. https://github.com/nlohmann/json/pull/3073 | |
3886 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& | |
3887 is_complete_type < | |
3888 detected_t<range_value_t, ConstructibleArrayType >>::value >> | |
3889 { | |
3890 using value_type = range_value_t<ConstructibleArrayType>; | |
3891 | |
3892 static constexpr bool value = | |
3893 std::is_same<value_type, | |
3894 typename BasicJsonType::array_t::value_type>::value || | |
3895 has_from_json<BasicJsonType, | |
3896 value_type>::value || | |
3897 has_non_default_from_json < | |
3898 BasicJsonType, | |
3899 value_type >::value; | |
3900 }; | |
3901 | |
3902 template<typename BasicJsonType, typename ConstructibleArrayType> | |
3903 struct is_constructible_array_type | |
3904 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {}; | |
3905 | |
3906 template<typename RealIntegerType, typename CompatibleNumberIntegerType, | |
3907 typename = void> | |
3908 struct is_compatible_integer_type_impl : std::false_type {}; | |
3909 | |
3910 template<typename RealIntegerType, typename CompatibleNumberIntegerType> | |
3911 struct is_compatible_integer_type_impl < | |
3912 RealIntegerType, CompatibleNumberIntegerType, | |
3913 enable_if_t < std::is_integral<RealIntegerType>::value&& | |
3914 std::is_integral<CompatibleNumberIntegerType>::value&& | |
3915 !std::is_same<bool, CompatibleNumberIntegerType>::value >> | |
3916 { | |
3917 // is there an assert somewhere on overflows? | |
3918 using RealLimits = std::numeric_limits<RealIntegerType>; | |
3919 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; | |
3920 | |
3921 static constexpr auto value = | |
3922 is_constructible<RealIntegerType, | |
3923 CompatibleNumberIntegerType>::value && | |
3924 CompatibleLimits::is_integer && | |
3925 RealLimits::is_signed == CompatibleLimits::is_signed; | |
3926 }; | |
3927 | |
3928 template<typename RealIntegerType, typename CompatibleNumberIntegerType> | |
3929 struct is_compatible_integer_type | |
3930 : is_compatible_integer_type_impl<RealIntegerType, | |
3931 CompatibleNumberIntegerType> {}; | |
3932 | |
3933 template<typename BasicJsonType, typename CompatibleType, typename = void> | |
3934 struct is_compatible_type_impl: std::false_type {}; | |
3935 | |
3936 template<typename BasicJsonType, typename CompatibleType> | |
3937 struct is_compatible_type_impl < | |
3938 BasicJsonType, CompatibleType, | |
3939 enable_if_t<is_complete_type<CompatibleType>::value >> | |
3940 { | |
3941 static constexpr bool value = | |
3942 has_to_json<BasicJsonType, CompatibleType>::value; | |
3943 }; | |
3944 | |
3945 template<typename BasicJsonType, typename CompatibleType> | |
3946 struct is_compatible_type | |
3947 : is_compatible_type_impl<BasicJsonType, CompatibleType> {}; | |
3948 | |
3949 template<typename T1, typename T2> | |
3950 struct is_constructible_tuple : std::false_type {}; | |
3951 | |
3952 template<typename T1, typename... Args> | |
3953 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {}; | |
3954 | |
3955 template<typename BasicJsonType, typename T> | |
3956 struct is_json_iterator_of : std::false_type {}; | |
3957 | |
3958 template<typename BasicJsonType> | |
3959 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {}; | |
3960 | |
3961 template<typename BasicJsonType> | |
3962 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type | |
3963 {}; | |
3964 | |
3965 // checks if a given type T is a template specialization of Primary | |
3966 template<template <typename...> class Primary, typename T> | |
3967 struct is_specialization_of : std::false_type {}; | |
3968 | |
3969 template<template <typename...> class Primary, typename... Args> | |
3970 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {}; | |
3971 | |
3972 template<typename T> | |
3973 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>; | |
3974 | |
3975 // checks if A and B are comparable using Compare functor | |
3976 template<typename Compare, typename A, typename B, typename = void> | |
3977 struct is_comparable : std::false_type {}; | |
3978 | |
3979 template<typename Compare, typename A, typename B> | |
3980 struct is_comparable<Compare, A, B, void_t< | |
3981 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), | |
3982 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>())) | |
3983 >> : std::true_type {}; | |
3984 | |
3985 template<typename T> | |
3986 using detect_is_transparent = typename T::is_transparent; | |
3987 | |
3988 // type trait to check if KeyType can be used as object key (without a BasicJsonType) | |
3989 // see is_usable_as_basic_json_key_type below | |
3990 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, | |
3991 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> | |
3992 using is_usable_as_key_type = typename std::conditional < | |
3993 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value | |
3994 && !(ExcludeObjectKeyType && std::is_same<KeyType, | |
3995 ObjectKeyType>::value) | |
3996 && (!RequireTransparentComparator | |
3997 || is_detected <detect_is_transparent, Comparator>::value) | |
3998 && !is_json_pointer<KeyType>::value, | |
3999 std::true_type, | |
4000 std::false_type >::type; | |
4001 | |
4002 // type trait to check if KeyType can be used as object key | |
4003 // true if: | |
4004 // - KeyType is comparable with BasicJsonType::object_t::key_type | |
4005 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type | |
4006 // - the comparator is transparent or RequireTransparentComparator is false | |
4007 // - KeyType is not a JSON iterator or json_pointer | |
4008 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, | |
4009 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> | |
4010 using is_usable_as_basic_json_key_type = typename std::conditional < | |
4011 is_usable_as_key_type<typename BasicJsonType::object_comparator_t, | |
4012 typename BasicJsonType::object_t::key_type, KeyTypeCVRef, | |
4013 RequireTransparentComparator, ExcludeObjectKeyType>::value | |
4014 && !is_json_iterator_of<BasicJsonType, KeyType>::value, | |
4015 std::true_type, | |
4016 std::false_type >::type; | |
4017 | |
4018 template<typename ObjectType, typename KeyType> | |
4019 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>())); | |
4020 | |
4021 // type trait to check if object_t has an erase() member functions accepting KeyType | |
4022 template<typename BasicJsonType, typename KeyType> | |
4023 using has_erase_with_key_type = typename std::conditional < | |
4024 is_detected < | |
4025 detect_erase_with_key_type, | |
4026 typename BasicJsonType::object_t, KeyType >::value, | |
4027 std::true_type, | |
4028 std::false_type >::type; | |
4029 | |
4030 // a naive helper to check if a type is an ordered_map (exploits the fact that | |
4031 // ordered_map inherits capacity() from std::vector) | |
4032 template <typename T> | |
4033 struct is_ordered_map | |
4034 { | |
4035 using one = char; | |
4036 | |
4037 struct two | |
4038 { | |
4039 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
4040 }; | |
4041 | |
4042 template <typename C> static one test( decltype(&C::capacity) ) ; | |
4043 template <typename C> static two test(...); | |
4044 | |
4045 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
4046 }; | |
4047 | |
4048 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) | |
4049 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 > | |
4050 T conditional_static_cast(U value) | |
4051 { | |
4052 return static_cast<T>(value); | |
4053 } | |
4054 | |
4055 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> | |
4056 T conditional_static_cast(U value) | |
4057 { | |
4058 return value; | |
4059 } | |
4060 | |
4061 template<typename... Types> | |
4062 using all_integral = conjunction<std::is_integral<Types>...>; | |
4063 | |
4064 template<typename... Types> | |
4065 using all_signed = conjunction<std::is_signed<Types>...>; | |
4066 | |
4067 template<typename... Types> | |
4068 using all_unsigned = conjunction<std::is_unsigned<Types>...>; | |
4069 | |
4070 // there's a disjunction trait in another PR; replace when merged | |
4071 template<typename... Types> | |
4072 using same_sign = std::integral_constant < bool, | |
4073 all_signed<Types...>::value || all_unsigned<Types...>::value >; | |
4074 | |
4075 template<typename OfType, typename T> | |
4076 using never_out_of_range = std::integral_constant < bool, | |
4077 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) | |
4078 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >; | |
4079 | |
4080 template<typename OfType, typename T, | |
4081 bool OfTypeSigned = std::is_signed<OfType>::value, | |
4082 bool TSigned = std::is_signed<T>::value> | |
4083 struct value_in_range_of_impl2; | |
4084 | |
4085 template<typename OfType, typename T> | |
4086 struct value_in_range_of_impl2<OfType, T, false, false> | |
4087 { | |
4088 static constexpr bool test(T val) | |
4089 { | |
4090 using CommonType = typename std::common_type<OfType, T>::type; | |
4091 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | |
4092 } | |
4093 }; | |
4094 | |
4095 template<typename OfType, typename T> | |
4096 struct value_in_range_of_impl2<OfType, T, true, false> | |
4097 { | |
4098 static constexpr bool test(T val) | |
4099 { | |
4100 using CommonType = typename std::common_type<OfType, T>::type; | |
4101 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | |
4102 } | |
4103 }; | |
4104 | |
4105 template<typename OfType, typename T> | |
4106 struct value_in_range_of_impl2<OfType, T, false, true> | |
4107 { | |
4108 static constexpr bool test(T val) | |
4109 { | |
4110 using CommonType = typename std::common_type<OfType, T>::type; | |
4111 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | |
4112 } | |
4113 }; | |
4114 | |
4115 template<typename OfType, typename T> | |
4116 struct value_in_range_of_impl2<OfType, T, true, true> | |
4117 { | |
4118 static constexpr bool test(T val) | |
4119 { | |
4120 using CommonType = typename std::common_type<OfType, T>::type; | |
4121 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) | |
4122 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); | |
4123 } | |
4124 }; | |
4125 | |
4126 template<typename OfType, typename T, | |
4127 bool NeverOutOfRange = never_out_of_range<OfType, T>::value, | |
4128 typename = detail::enable_if_t<all_integral<OfType, T>::value>> | |
4129 struct value_in_range_of_impl1; | |
4130 | |
4131 template<typename OfType, typename T> | |
4132 struct value_in_range_of_impl1<OfType, T, false> | |
4133 { | |
4134 static constexpr bool test(T val) | |
4135 { | |
4136 return value_in_range_of_impl2<OfType, T>::test(val); | |
4137 } | |
4138 }; | |
4139 | |
4140 template<typename OfType, typename T> | |
4141 struct value_in_range_of_impl1<OfType, T, true> | |
4142 { | |
4143 static constexpr bool test(T /*val*/) | |
4144 { | |
4145 return true; | |
4146 } | |
4147 }; | |
4148 | |
4149 template<typename OfType, typename T> | |
4150 inline constexpr bool value_in_range_of(T val) | |
4151 { | |
4152 return value_in_range_of_impl1<OfType, T>::test(val); | |
4153 } | |
4154 | |
4155 template<bool Value> | |
4156 using bool_constant = std::integral_constant<bool, Value>; | |
4157 | |
4158 /////////////////////////////////////////////////////////////////////////////// | |
4159 // is_c_string | |
4160 /////////////////////////////////////////////////////////////////////////////// | |
4161 | |
4162 namespace impl | |
4163 { | |
4164 | |
4165 template<typename T> | |
4166 inline constexpr bool is_c_string() | |
4167 { | |
4168 using TUnExt = typename std::remove_extent<T>::type; | |
4169 using TUnCVExt = typename std::remove_cv<TUnExt>::type; | |
4170 using TUnPtr = typename std::remove_pointer<T>::type; | |
4171 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type; | |
4172 return | |
4173 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) | |
4174 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value); | |
4175 } | |
4176 | |
4177 } // namespace impl | |
4178 | |
4179 // checks whether T is a [cv] char */[cv] char[] C string | |
4180 template<typename T> | |
4181 struct is_c_string : bool_constant<impl::is_c_string<T>()> {}; | |
4182 | |
4183 template<typename T> | |
4184 using is_c_string_uncvref = is_c_string<uncvref_t<T>>; | |
4185 | |
4186 /////////////////////////////////////////////////////////////////////////////// | |
4187 // is_transparent | |
4188 /////////////////////////////////////////////////////////////////////////////// | |
4189 | |
4190 namespace impl | |
4191 { | |
4192 | |
4193 template<typename T> | |
4194 inline constexpr bool is_transparent() | |
4195 { | |
4196 return is_detected<detect_is_transparent, T>::value; | |
4197 } | |
4198 | |
4199 } // namespace impl | |
4200 | |
4201 // checks whether T has a member named is_transparent | |
4202 template<typename T> | |
4203 struct is_transparent : bool_constant<impl::is_transparent<T>()> {}; | |
4204 | |
4205 /////////////////////////////////////////////////////////////////////////////// | |
4206 | |
4207 } // namespace detail | |
4208 NLOHMANN_JSON_NAMESPACE_END | |
4209 | |
4210 // #include <nlohmann/detail/string_concat.hpp> | |
4211 // __ _____ _____ _____ | |
4212 // __| | __| | | | JSON for Modern C++ | |
4213 // | | |__ | | | | | | version 3.11.3 | |
4214 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
4215 // | |
4216 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
4217 // SPDX-License-Identifier: MIT | |
4218 | |
4219 | |
4220 | |
4221 #include <cstring> // strlen | |
4222 #include <string> // string | |
4223 #include <utility> // forward | |
4224 | |
4225 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
4226 | |
4227 // #include <nlohmann/detail/meta/detected.hpp> | |
4228 | |
4229 | |
4230 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4231 namespace detail | |
4232 { | |
4233 | |
4234 inline std::size_t concat_length() | |
4235 { | |
4236 return 0; | |
4237 } | |
4238 | |
4239 template<typename... Args> | |
4240 inline std::size_t concat_length(const char* cstr, const Args& ... rest); | |
4241 | |
4242 template<typename StringType, typename... Args> | |
4243 inline std::size_t concat_length(const StringType& str, const Args& ... rest); | |
4244 | |
4245 template<typename... Args> | |
4246 inline std::size_t concat_length(const char /*c*/, const Args& ... rest) | |
4247 { | |
4248 return 1 + concat_length(rest...); | |
4249 } | |
4250 | |
4251 template<typename... Args> | |
4252 inline std::size_t concat_length(const char* cstr, const Args& ... rest) | |
4253 { | |
4254 // cppcheck-suppress ignoredReturnValue | |
4255 return ::strlen(cstr) + concat_length(rest...); | |
4256 } | |
4257 | |
4258 template<typename StringType, typename... Args> | |
4259 inline std::size_t concat_length(const StringType& str, const Args& ... rest) | |
4260 { | |
4261 return str.size() + concat_length(rest...); | |
4262 } | |
4263 | |
4264 template<typename OutStringType> | |
4265 inline void concat_into(OutStringType& /*out*/) | |
4266 {} | |
4267 | |
4268 template<typename StringType, typename Arg> | |
4269 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ())); | |
4270 | |
4271 template<typename StringType, typename Arg> | |
4272 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>; | |
4273 | |
4274 template<typename StringType, typename Arg> | |
4275 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ()); | |
4276 | |
4277 template<typename StringType, typename Arg> | |
4278 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>; | |
4279 | |
4280 template<typename StringType, typename Arg> | |
4281 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end())); | |
4282 | |
4283 template<typename StringType, typename Arg> | |
4284 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>; | |
4285 | |
4286 template<typename StringType, typename Arg> | |
4287 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size())); | |
4288 | |
4289 template<typename StringType, typename Arg> | |
4290 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>; | |
4291 | |
4292 template < typename OutStringType, typename Arg, typename... Args, | |
4293 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4294 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 > | |
4295 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); | |
4296 | |
4297 template < typename OutStringType, typename Arg, typename... Args, | |
4298 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4299 && !detect_string_can_append_op<OutStringType, Arg>::value | |
4300 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 > | |
4301 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); | |
4302 | |
4303 template < typename OutStringType, typename Arg, typename... Args, | |
4304 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4305 && !detect_string_can_append_op<OutStringType, Arg>::value | |
4306 && !detect_string_can_append_iter<OutStringType, Arg>::value | |
4307 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 > | |
4308 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); | |
4309 | |
4310 template<typename OutStringType, typename Arg, typename... Args, | |
4311 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0> | |
4312 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) | |
4313 { | |
4314 out.append(std::forward<Arg>(arg)); | |
4315 concat_into(out, std::forward<Args>(rest)...); | |
4316 } | |
4317 | |
4318 template < typename OutStringType, typename Arg, typename... Args, | |
4319 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4320 && detect_string_can_append_op<OutStringType, Arg>::value, int > > | |
4321 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) | |
4322 { | |
4323 out += std::forward<Arg>(arg); | |
4324 concat_into(out, std::forward<Args>(rest)...); | |
4325 } | |
4326 | |
4327 template < typename OutStringType, typename Arg, typename... Args, | |
4328 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4329 && !detect_string_can_append_op<OutStringType, Arg>::value | |
4330 && detect_string_can_append_iter<OutStringType, Arg>::value, int > > | |
4331 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) | |
4332 { | |
4333 out.append(arg.begin(), arg.end()); | |
4334 concat_into(out, std::forward<Args>(rest)...); | |
4335 } | |
4336 | |
4337 template < typename OutStringType, typename Arg, typename... Args, | |
4338 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value | |
4339 && !detect_string_can_append_op<OutStringType, Arg>::value | |
4340 && !detect_string_can_append_iter<OutStringType, Arg>::value | |
4341 && detect_string_can_append_data<OutStringType, Arg>::value, int > > | |
4342 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) | |
4343 { | |
4344 out.append(arg.data(), arg.size()); | |
4345 concat_into(out, std::forward<Args>(rest)...); | |
4346 } | |
4347 | |
4348 template<typename OutStringType = std::string, typename... Args> | |
4349 inline OutStringType concat(Args && ... args) | |
4350 { | |
4351 OutStringType str; | |
4352 str.reserve(concat_length(args...)); | |
4353 concat_into(str, std::forward<Args>(args)...); | |
4354 return str; | |
4355 } | |
4356 | |
4357 } // namespace detail | |
4358 NLOHMANN_JSON_NAMESPACE_END | |
4359 | |
4360 | |
4361 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4362 namespace detail | |
4363 { | |
4364 | |
4365 //////////////// | |
4366 // exceptions // | |
4367 //////////////// | |
4368 | |
4369 /// @brief general exception of the @ref basic_json class | |
4370 /// @sa https://json.nlohmann.me/api/basic_json/exception/ | |
4371 class exception : public std::exception | |
4372 { | |
4373 public: | |
4374 /// returns the explanatory string | |
4375 const char* what() const noexcept override | |
4376 { | |
4377 return m.what(); | |
4378 } | |
4379 | |
4380 /// the id of the exception | |
4381 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) | |
4382 | |
4383 protected: | |
4384 JSON_HEDLEY_NON_NULL(3) | |
4385 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) | |
4386 | |
4387 static std::string name(const std::string& ename, int id_) | |
4388 { | |
4389 return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); | |
4390 } | |
4391 | |
4392 static std::string diagnostics(std::nullptr_t /*leaf_element*/) | |
4393 { | |
4394 return ""; | |
4395 } | |
4396 | |
4397 template<typename BasicJsonType> | |
4398 static std::string diagnostics(const BasicJsonType* leaf_element) | |
4399 { | |
4400 #if JSON_DIAGNOSTICS | |
4401 std::vector<std::string> tokens; | |
4402 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) | |
4403 { | |
4404 switch (current->m_parent->type()) | |
4405 { | |
4406 case value_t::array: | |
4407 { | |
4408 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) | |
4409 { | |
4410 if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) | |
4411 { | |
4412 tokens.emplace_back(std::to_string(i)); | |
4413 break; | |
4414 } | |
4415 } | |
4416 break; | |
4417 } | |
4418 | |
4419 case value_t::object: | |
4420 { | |
4421 for (const auto& element : *current->m_parent->m_data.m_value.object) | |
4422 { | |
4423 if (&element.second == current) | |
4424 { | |
4425 tokens.emplace_back(element.first.c_str()); | |
4426 break; | |
4427 } | |
4428 } | |
4429 break; | |
4430 } | |
4431 | |
4432 case value_t::null: // LCOV_EXCL_LINE | |
4433 case value_t::string: // LCOV_EXCL_LINE | |
4434 case value_t::boolean: // LCOV_EXCL_LINE | |
4435 case value_t::number_integer: // LCOV_EXCL_LINE | |
4436 case value_t::number_unsigned: // LCOV_EXCL_LINE | |
4437 case value_t::number_float: // LCOV_EXCL_LINE | |
4438 case value_t::binary: // LCOV_EXCL_LINE | |
4439 case value_t::discarded: // LCOV_EXCL_LINE | |
4440 default: // LCOV_EXCL_LINE | |
4441 break; // LCOV_EXCL_LINE | |
4442 } | |
4443 } | |
4444 | |
4445 if (tokens.empty()) | |
4446 { | |
4447 return ""; | |
4448 } | |
4449 | |
4450 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, | |
4451 [](const std::string & a, const std::string & b) | |
4452 { | |
4453 return concat(a, '/', detail::escape(b)); | |
4454 }); | |
4455 return concat('(', str, ") "); | |
4456 #else | |
4457 static_cast<void>(leaf_element); | |
4458 return ""; | |
4459 #endif | |
4460 } | |
4461 | |
4462 private: | |
4463 /// an exception object as storage for error messages | |
4464 std::runtime_error m; | |
4465 }; | |
4466 | |
4467 /// @brief exception indicating a parse error | |
4468 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ | |
4469 class parse_error : public exception | |
4470 { | |
4471 public: | |
4472 /*! | |
4473 @brief create a parse error exception | |
4474 @param[in] id_ the id of the exception | |
4475 @param[in] pos the position where the error occurred (or with | |
4476 chars_read_total=0 if the position cannot be | |
4477 determined) | |
4478 @param[in] what_arg the explanatory string | |
4479 @return parse_error object | |
4480 */ | |
4481 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4482 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) | |
4483 { | |
4484 const std::string w = concat(exception::name("parse_error", id_), "parse error", | |
4485 position_string(pos), ": ", exception::diagnostics(context), what_arg); | |
4486 return {id_, pos.chars_read_total, w.c_str()}; | |
4487 } | |
4488 | |
4489 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4490 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) | |
4491 { | |
4492 const std::string w = concat(exception::name("parse_error", id_), "parse error", | |
4493 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), | |
4494 ": ", exception::diagnostics(context), what_arg); | |
4495 return {id_, byte_, w.c_str()}; | |
4496 } | |
4497 | |
4498 /*! | |
4499 @brief byte index of the parse error | |
4500 | |
4501 The byte index of the last read character in the input file. | |
4502 | |
4503 @note For an input with n bytes, 1 is the index of the first character and | |
4504 n+1 is the index of the terminating null byte or the end of file. | |
4505 This also holds true when reading a byte vector (CBOR or MessagePack). | |
4506 */ | |
4507 const std::size_t byte; | |
4508 | |
4509 private: | |
4510 parse_error(int id_, std::size_t byte_, const char* what_arg) | |
4511 : exception(id_, what_arg), byte(byte_) {} | |
4512 | |
4513 static std::string position_string(const position_t& pos) | |
4514 { | |
4515 return concat(" at line ", std::to_string(pos.lines_read + 1), | |
4516 ", column ", std::to_string(pos.chars_read_current_line)); | |
4517 } | |
4518 }; | |
4519 | |
4520 /// @brief exception indicating errors with iterators | |
4521 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ | |
4522 class invalid_iterator : public exception | |
4523 { | |
4524 public: | |
4525 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4526 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) | |
4527 { | |
4528 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); | |
4529 return {id_, w.c_str()}; | |
4530 } | |
4531 | |
4532 private: | |
4533 JSON_HEDLEY_NON_NULL(3) | |
4534 invalid_iterator(int id_, const char* what_arg) | |
4535 : exception(id_, what_arg) {} | |
4536 }; | |
4537 | |
4538 /// @brief exception indicating executing a member function with a wrong type | |
4539 /// @sa https://json.nlohmann.me/api/basic_json/type_error/ | |
4540 class type_error : public exception | |
4541 { | |
4542 public: | |
4543 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4544 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) | |
4545 { | |
4546 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); | |
4547 return {id_, w.c_str()}; | |
4548 } | |
4549 | |
4550 private: | |
4551 JSON_HEDLEY_NON_NULL(3) | |
4552 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} | |
4553 }; | |
4554 | |
4555 /// @brief exception indicating access out of the defined range | |
4556 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ | |
4557 class out_of_range : public exception | |
4558 { | |
4559 public: | |
4560 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4561 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) | |
4562 { | |
4563 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); | |
4564 return {id_, w.c_str()}; | |
4565 } | |
4566 | |
4567 private: | |
4568 JSON_HEDLEY_NON_NULL(3) | |
4569 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} | |
4570 }; | |
4571 | |
4572 /// @brief exception indicating other library errors | |
4573 /// @sa https://json.nlohmann.me/api/basic_json/other_error/ | |
4574 class other_error : public exception | |
4575 { | |
4576 public: | |
4577 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> | |
4578 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) | |
4579 { | |
4580 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); | |
4581 return {id_, w.c_str()}; | |
4582 } | |
4583 | |
4584 private: | |
4585 JSON_HEDLEY_NON_NULL(3) | |
4586 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} | |
4587 }; | |
4588 | |
4589 } // namespace detail | |
4590 NLOHMANN_JSON_NAMESPACE_END | |
4591 | |
4592 // #include <nlohmann/detail/macro_scope.hpp> | |
4593 | |
4594 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
4595 | |
4596 // #include <nlohmann/detail/meta/identity_tag.hpp> | |
4597 // __ _____ _____ _____ | |
4598 // __| | __| | | | JSON for Modern C++ | |
4599 // | | |__ | | | | | | version 3.11.3 | |
4600 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
4601 // | |
4602 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
4603 // SPDX-License-Identifier: MIT | |
4604 | |
4605 | |
4606 | |
4607 // #include <nlohmann/detail/abi_macros.hpp> | |
4608 | |
4609 | |
4610 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4611 namespace detail | |
4612 { | |
4613 | |
4614 // dispatching helper struct | |
4615 template <class T> struct identity_tag {}; | |
4616 | |
4617 } // namespace detail | |
4618 NLOHMANN_JSON_NAMESPACE_END | |
4619 | |
4620 // #include <nlohmann/detail/meta/std_fs.hpp> | |
4621 // __ _____ _____ _____ | |
4622 // __| | __| | | | JSON for Modern C++ | |
4623 // | | |__ | | | | | | version 3.11.3 | |
4624 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
4625 // | |
4626 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
4627 // SPDX-License-Identifier: MIT | |
4628 | |
4629 | |
4630 | |
4631 // #include <nlohmann/detail/macro_scope.hpp> | |
4632 | |
4633 | |
4634 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
4635 #include <experimental/filesystem> | |
4636 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4637 namespace detail | |
4638 { | |
4639 namespace std_fs = std::experimental::filesystem; | |
4640 } // namespace detail | |
4641 NLOHMANN_JSON_NAMESPACE_END | |
4642 #elif JSON_HAS_FILESYSTEM | |
4643 #include <filesystem> | |
4644 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4645 namespace detail | |
4646 { | |
4647 namespace std_fs = std::filesystem; | |
4648 } // namespace detail | |
4649 NLOHMANN_JSON_NAMESPACE_END | |
4650 #endif | |
4651 | |
4652 // #include <nlohmann/detail/meta/type_traits.hpp> | |
4653 | |
4654 // #include <nlohmann/detail/string_concat.hpp> | |
4655 | |
4656 // #include <nlohmann/detail/value_t.hpp> | |
4657 | |
4658 | |
4659 NLOHMANN_JSON_NAMESPACE_BEGIN | |
4660 namespace detail | |
4661 { | |
4662 | |
4663 template<typename BasicJsonType> | |
4664 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) | |
4665 { | |
4666 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) | |
4667 { | |
4668 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); | |
4669 } | |
4670 n = nullptr; | |
4671 } | |
4672 | |
4673 // overloads for basic_json template parameters | |
4674 template < typename BasicJsonType, typename ArithmeticType, | |
4675 enable_if_t < std::is_arithmetic<ArithmeticType>::value&& | |
4676 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, | |
4677 int > = 0 > | |
4678 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) | |
4679 { | |
4680 switch (static_cast<value_t>(j)) | |
4681 { | |
4682 case value_t::number_unsigned: | |
4683 { | |
4684 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); | |
4685 break; | |
4686 } | |
4687 case value_t::number_integer: | |
4688 { | |
4689 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); | |
4690 break; | |
4691 } | |
4692 case value_t::number_float: | |
4693 { | |
4694 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); | |
4695 break; | |
4696 } | |
4697 | |
4698 case value_t::null: | |
4699 case value_t::object: | |
4700 case value_t::array: | |
4701 case value_t::string: | |
4702 case value_t::boolean: | |
4703 case value_t::binary: | |
4704 case value_t::discarded: | |
4705 default: | |
4706 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); | |
4707 } | |
4708 } | |
4709 | |
4710 template<typename BasicJsonType> | |
4711 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) | |
4712 { | |
4713 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) | |
4714 { | |
4715 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); | |
4716 } | |
4717 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); | |
4718 } | |
4719 | |
4720 template<typename BasicJsonType> | |
4721 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) | |
4722 { | |
4723 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | |
4724 { | |
4725 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | |
4726 } | |
4727 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | |
4728 } | |
4729 | |
4730 template < | |
4731 typename BasicJsonType, typename StringType, | |
4732 enable_if_t < | |
4733 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value | |
4734 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value | |
4735 && !std::is_same<typename BasicJsonType::string_t, StringType>::value | |
4736 && !is_json_ref<StringType>::value, int > = 0 > | |
4737 inline void from_json(const BasicJsonType& j, StringType& s) | |
4738 { | |
4739 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | |
4740 { | |
4741 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | |
4742 } | |
4743 | |
4744 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | |
4745 } | |
4746 | |
4747 template<typename BasicJsonType> | |
4748 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) | |
4749 { | |
4750 get_arithmetic_value(j, val); | |
4751 } | |
4752 | |
4753 template<typename BasicJsonType> | |
4754 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) | |
4755 { | |
4756 get_arithmetic_value(j, val); | |
4757 } | |
4758 | |
4759 template<typename BasicJsonType> | |
4760 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) | |
4761 { | |
4762 get_arithmetic_value(j, val); | |
4763 } | |
4764 | |
4765 #if !JSON_DISABLE_ENUM_SERIALIZATION | |
4766 template<typename BasicJsonType, typename EnumType, | |
4767 enable_if_t<std::is_enum<EnumType>::value, int> = 0> | |
4768 inline void from_json(const BasicJsonType& j, EnumType& e) | |
4769 { | |
4770 typename std::underlying_type<EnumType>::type val; | |
4771 get_arithmetic_value(j, val); | |
4772 e = static_cast<EnumType>(val); | |
4773 } | |
4774 #endif // JSON_DISABLE_ENUM_SERIALIZATION | |
4775 | |
4776 // forward_list doesn't have an insert method | |
4777 template<typename BasicJsonType, typename T, typename Allocator, | |
4778 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> | |
4779 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) | |
4780 { | |
4781 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
4782 { | |
4783 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
4784 } | |
4785 l.clear(); | |
4786 std::transform(j.rbegin(), j.rend(), | |
4787 std::front_inserter(l), [](const BasicJsonType & i) | |
4788 { | |
4789 return i.template get<T>(); | |
4790 }); | |
4791 } | |
4792 | |
4793 // valarray doesn't have an insert method | |
4794 template<typename BasicJsonType, typename T, | |
4795 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> | |
4796 inline void from_json(const BasicJsonType& j, std::valarray<T>& l) | |
4797 { | |
4798 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
4799 { | |
4800 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
4801 } | |
4802 l.resize(j.size()); | |
4803 std::transform(j.begin(), j.end(), std::begin(l), | |
4804 [](const BasicJsonType & elem) | |
4805 { | |
4806 return elem.template get<T>(); | |
4807 }); | |
4808 } | |
4809 | |
4810 template<typename BasicJsonType, typename T, std::size_t N> | |
4811 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
4812 -> decltype(j.template get<T>(), void()) | |
4813 { | |
4814 for (std::size_t i = 0; i < N; ++i) | |
4815 { | |
4816 arr[i] = j.at(i).template get<T>(); | |
4817 } | |
4818 } | |
4819 | |
4820 template<typename BasicJsonType> | |
4821 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) | |
4822 { | |
4823 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); | |
4824 } | |
4825 | |
4826 template<typename BasicJsonType, typename T, std::size_t N> | |
4827 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, | |
4828 priority_tag<2> /*unused*/) | |
4829 -> decltype(j.template get<T>(), void()) | |
4830 { | |
4831 for (std::size_t i = 0; i < N; ++i) | |
4832 { | |
4833 arr[i] = j.at(i).template get<T>(); | |
4834 } | |
4835 } | |
4836 | |
4837 template<typename BasicJsonType, typename ConstructibleArrayType, | |
4838 enable_if_t< | |
4839 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, | |
4840 int> = 0> | |
4841 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) | |
4842 -> decltype( | |
4843 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), | |
4844 j.template get<typename ConstructibleArrayType::value_type>(), | |
4845 void()) | |
4846 { | |
4847 using std::end; | |
4848 | |
4849 ConstructibleArrayType ret; | |
4850 ret.reserve(j.size()); | |
4851 std::transform(j.begin(), j.end(), | |
4852 std::inserter(ret, end(ret)), [](const BasicJsonType & i) | |
4853 { | |
4854 // get<BasicJsonType>() returns *this, this won't call a from_json | |
4855 // method when value_type is BasicJsonType | |
4856 return i.template get<typename ConstructibleArrayType::value_type>(); | |
4857 }); | |
4858 arr = std::move(ret); | |
4859 } | |
4860 | |
4861 template<typename BasicJsonType, typename ConstructibleArrayType, | |
4862 enable_if_t< | |
4863 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, | |
4864 int> = 0> | |
4865 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, | |
4866 priority_tag<0> /*unused*/) | |
4867 { | |
4868 using std::end; | |
4869 | |
4870 ConstructibleArrayType ret; | |
4871 std::transform( | |
4872 j.begin(), j.end(), std::inserter(ret, end(ret)), | |
4873 [](const BasicJsonType & i) | |
4874 { | |
4875 // get<BasicJsonType>() returns *this, this won't call a from_json | |
4876 // method when value_type is BasicJsonType | |
4877 return i.template get<typename ConstructibleArrayType::value_type>(); | |
4878 }); | |
4879 arr = std::move(ret); | |
4880 } | |
4881 | |
4882 template < typename BasicJsonType, typename ConstructibleArrayType, | |
4883 enable_if_t < | |
4884 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& | |
4885 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& | |
4886 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& | |
4887 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& | |
4888 !is_basic_json<ConstructibleArrayType>::value, | |
4889 int > = 0 > | |
4890 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) | |
4891 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), | |
4892 j.template get<typename ConstructibleArrayType::value_type>(), | |
4893 void()) | |
4894 { | |
4895 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
4896 { | |
4897 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
4898 } | |
4899 | |
4900 from_json_array_impl(j, arr, priority_tag<3> {}); | |
4901 } | |
4902 | |
4903 template < typename BasicJsonType, typename T, std::size_t... Idx > | |
4904 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, | |
4905 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) | |
4906 { | |
4907 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; | |
4908 } | |
4909 | |
4910 template < typename BasicJsonType, typename T, std::size_t N > | |
4911 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) | |
4912 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) | |
4913 { | |
4914 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
4915 { | |
4916 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
4917 } | |
4918 | |
4919 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); | |
4920 } | |
4921 | |
4922 template<typename BasicJsonType> | |
4923 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) | |
4924 { | |
4925 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) | |
4926 { | |
4927 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); | |
4928 } | |
4929 | |
4930 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); | |
4931 } | |
4932 | |
4933 template<typename BasicJsonType, typename ConstructibleObjectType, | |
4934 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> | |
4935 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) | |
4936 { | |
4937 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) | |
4938 { | |
4939 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); | |
4940 } | |
4941 | |
4942 ConstructibleObjectType ret; | |
4943 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); | |
4944 using value_type = typename ConstructibleObjectType::value_type; | |
4945 std::transform( | |
4946 inner_object->begin(), inner_object->end(), | |
4947 std::inserter(ret, ret.begin()), | |
4948 [](typename BasicJsonType::object_t::value_type const & p) | |
4949 { | |
4950 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); | |
4951 }); | |
4952 obj = std::move(ret); | |
4953 } | |
4954 | |
4955 // overload for arithmetic types, not chosen for basic_json template arguments | |
4956 // (BooleanType, etc..); note: Is it really necessary to provide explicit | |
4957 // overloads for boolean_t etc. in case of a custom BooleanType which is not | |
4958 // an arithmetic type? | |
4959 template < typename BasicJsonType, typename ArithmeticType, | |
4960 enable_if_t < | |
4961 std::is_arithmetic<ArithmeticType>::value&& | |
4962 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& | |
4963 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& | |
4964 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& | |
4965 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, | |
4966 int > = 0 > | |
4967 inline void from_json(const BasicJsonType& j, ArithmeticType& val) | |
4968 { | |
4969 switch (static_cast<value_t>(j)) | |
4970 { | |
4971 case value_t::number_unsigned: | |
4972 { | |
4973 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); | |
4974 break; | |
4975 } | |
4976 case value_t::number_integer: | |
4977 { | |
4978 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); | |
4979 break; | |
4980 } | |
4981 case value_t::number_float: | |
4982 { | |
4983 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); | |
4984 break; | |
4985 } | |
4986 case value_t::boolean: | |
4987 { | |
4988 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); | |
4989 break; | |
4990 } | |
4991 | |
4992 case value_t::null: | |
4993 case value_t::object: | |
4994 case value_t::array: | |
4995 case value_t::string: | |
4996 case value_t::binary: | |
4997 case value_t::discarded: | |
4998 default: | |
4999 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); | |
5000 } | |
5001 } | |
5002 | |
5003 template<typename BasicJsonType, typename... Args, std::size_t... Idx> | |
5004 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) | |
5005 { | |
5006 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); | |
5007 } | |
5008 | |
5009 template < typename BasicJsonType, class A1, class A2 > | |
5010 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) | |
5011 { | |
5012 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), | |
5013 std::forward<BasicJsonType>(j).at(1).template get<A2>()}; | |
5014 } | |
5015 | |
5016 template<typename BasicJsonType, typename A1, typename A2> | |
5017 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) | |
5018 { | |
5019 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); | |
5020 } | |
5021 | |
5022 template<typename BasicJsonType, typename... Args> | |
5023 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) | |
5024 { | |
5025 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); | |
5026 } | |
5027 | |
5028 template<typename BasicJsonType, typename... Args> | |
5029 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) | |
5030 { | |
5031 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); | |
5032 } | |
5033 | |
5034 template<typename BasicJsonType, typename TupleRelated> | |
5035 auto from_json(BasicJsonType&& j, TupleRelated&& t) | |
5036 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) | |
5037 { | |
5038 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
5039 { | |
5040 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
5041 } | |
5042 | |
5043 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); | |
5044 } | |
5045 | |
5046 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, | |
5047 typename = enable_if_t < !std::is_constructible < | |
5048 typename BasicJsonType::string_t, Key >::value >> | |
5049 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) | |
5050 { | |
5051 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
5052 { | |
5053 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
5054 } | |
5055 m.clear(); | |
5056 for (const auto& p : j) | |
5057 { | |
5058 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) | |
5059 { | |
5060 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); | |
5061 } | |
5062 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); | |
5063 } | |
5064 } | |
5065 | |
5066 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, | |
5067 typename = enable_if_t < !std::is_constructible < | |
5068 typename BasicJsonType::string_t, Key >::value >> | |
5069 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) | |
5070 { | |
5071 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) | |
5072 { | |
5073 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); | |
5074 } | |
5075 m.clear(); | |
5076 for (const auto& p : j) | |
5077 { | |
5078 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) | |
5079 { | |
5080 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); | |
5081 } | |
5082 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); | |
5083 } | |
5084 } | |
5085 | |
5086 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
5087 template<typename BasicJsonType> | |
5088 inline void from_json(const BasicJsonType& j, std_fs::path& p) | |
5089 { | |
5090 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) | |
5091 { | |
5092 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); | |
5093 } | |
5094 p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); | |
5095 } | |
5096 #endif | |
5097 | |
5098 struct from_json_fn | |
5099 { | |
5100 template<typename BasicJsonType, typename T> | |
5101 auto operator()(const BasicJsonType& j, T&& val) const | |
5102 noexcept(noexcept(from_json(j, std::forward<T>(val)))) | |
5103 -> decltype(from_json(j, std::forward<T>(val))) | |
5104 { | |
5105 return from_json(j, std::forward<T>(val)); | |
5106 } | |
5107 }; | |
5108 | |
5109 } // namespace detail | |
5110 | |
5111 #ifndef JSON_HAS_CPP_17 | |
5112 /// namespace to hold default `from_json` function | |
5113 /// to see why this is required: | |
5114 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html | |
5115 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) | |
5116 { | |
5117 #endif | |
5118 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) | |
5119 detail::static_const<detail::from_json_fn>::value; | |
5120 #ifndef JSON_HAS_CPP_17 | |
5121 } // namespace | |
5122 #endif | |
5123 | |
5124 NLOHMANN_JSON_NAMESPACE_END | |
5125 | |
5126 // #include <nlohmann/detail/conversions/to_json.hpp> | |
5127 // __ _____ _____ _____ | |
5128 // __| | __| | | | JSON for Modern C++ | |
5129 // | | |__ | | | | | | version 3.11.3 | |
5130 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
5131 // | |
5132 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
5133 // SPDX-License-Identifier: MIT | |
5134 | |
5135 | |
5136 | |
5137 #include <algorithm> // copy | |
5138 #include <iterator> // begin, end | |
5139 #include <string> // string | |
5140 #include <tuple> // tuple, get | |
5141 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type | |
5142 #include <utility> // move, forward, declval, pair | |
5143 #include <valarray> // valarray | |
5144 #include <vector> // vector | |
5145 | |
5146 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> | |
5147 // __ _____ _____ _____ | |
5148 // __| | __| | | | JSON for Modern C++ | |
5149 // | | |__ | | | | | | version 3.11.3 | |
5150 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
5151 // | |
5152 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
5153 // SPDX-License-Identifier: MIT | |
5154 | |
5155 | |
5156 | |
5157 #include <cstddef> // size_t | |
5158 #include <iterator> // input_iterator_tag | |
5159 #include <string> // string, to_string | |
5160 #include <tuple> // tuple_size, get, tuple_element | |
5161 #include <utility> // move | |
5162 | |
5163 #if JSON_HAS_RANGES | |
5164 #include <ranges> // enable_borrowed_range | |
5165 #endif | |
5166 | |
5167 // #include <nlohmann/detail/abi_macros.hpp> | |
5168 | |
5169 // #include <nlohmann/detail/meta/type_traits.hpp> | |
5170 | |
5171 // #include <nlohmann/detail/value_t.hpp> | |
5172 | |
5173 | |
5174 NLOHMANN_JSON_NAMESPACE_BEGIN | |
5175 namespace detail | |
5176 { | |
5177 | |
5178 template<typename string_type> | |
5179 void int_to_string( string_type& target, std::size_t value ) | |
5180 { | |
5181 // For ADL | |
5182 using std::to_string; | |
5183 target = to_string(value); | |
5184 } | |
5185 template<typename IteratorType> class iteration_proxy_value | |
5186 { | |
5187 public: | |
5188 using difference_type = std::ptrdiff_t; | |
5189 using value_type = iteration_proxy_value; | |
5190 using pointer = value_type *; | |
5191 using reference = value_type &; | |
5192 using iterator_category = std::input_iterator_tag; | |
5193 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; | |
5194 | |
5195 private: | |
5196 /// the iterator | |
5197 IteratorType anchor{}; | |
5198 /// an index for arrays (used to create key names) | |
5199 std::size_t array_index = 0; | |
5200 /// last stringified array index | |
5201 mutable std::size_t array_index_last = 0; | |
5202 /// a string representation of the array index | |
5203 mutable string_type array_index_str = "0"; | |
5204 /// an empty string (to return a reference for primitive values) | |
5205 string_type empty_str{}; | |
5206 | |
5207 public: | |
5208 explicit iteration_proxy_value() = default; | |
5209 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) | |
5210 noexcept(std::is_nothrow_move_constructible<IteratorType>::value | |
5211 && std::is_nothrow_default_constructible<string_type>::value) | |
5212 : anchor(std::move(it)) | |
5213 , array_index(array_index_) | |
5214 {} | |
5215 | |
5216 iteration_proxy_value(iteration_proxy_value const&) = default; | |
5217 iteration_proxy_value& operator=(iteration_proxy_value const&) = default; | |
5218 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions | |
5219 iteration_proxy_value(iteration_proxy_value&&) | |
5220 noexcept(std::is_nothrow_move_constructible<IteratorType>::value | |
5221 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) | |
5222 iteration_proxy_value& operator=(iteration_proxy_value&&) | |
5223 noexcept(std::is_nothrow_move_assignable<IteratorType>::value | |
5224 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) | |
5225 ~iteration_proxy_value() = default; | |
5226 | |
5227 /// dereference operator (needed for range-based for) | |
5228 const iteration_proxy_value& operator*() const | |
5229 { | |
5230 return *this; | |
5231 } | |
5232 | |
5233 /// increment operator (needed for range-based for) | |
5234 iteration_proxy_value& operator++() | |
5235 { | |
5236 ++anchor; | |
5237 ++array_index; | |
5238 | |
5239 return *this; | |
5240 } | |
5241 | |
5242 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) | |
5243 { | |
5244 auto tmp = iteration_proxy_value(anchor, array_index); | |
5245 ++anchor; | |
5246 ++array_index; | |
5247 return tmp; | |
5248 } | |
5249 | |
5250 /// equality operator (needed for InputIterator) | |
5251 bool operator==(const iteration_proxy_value& o) const | |
5252 { | |
5253 return anchor == o.anchor; | |
5254 } | |
5255 | |
5256 /// inequality operator (needed for range-based for) | |
5257 bool operator!=(const iteration_proxy_value& o) const | |
5258 { | |
5259 return anchor != o.anchor; | |
5260 } | |
5261 | |
5262 /// return key of the iterator | |
5263 const string_type& key() const | |
5264 { | |
5265 JSON_ASSERT(anchor.m_object != nullptr); | |
5266 | |
5267 switch (anchor.m_object->type()) | |
5268 { | |
5269 // use integer array index as key | |
5270 case value_t::array: | |
5271 { | |
5272 if (array_index != array_index_last) | |
5273 { | |
5274 int_to_string( array_index_str, array_index ); | |
5275 array_index_last = array_index; | |
5276 } | |
5277 return array_index_str; | |
5278 } | |
5279 | |
5280 // use key from the object | |
5281 case value_t::object: | |
5282 return anchor.key(); | |
5283 | |
5284 // use an empty key for all primitive types | |
5285 case value_t::null: | |
5286 case value_t::string: | |
5287 case value_t::boolean: | |
5288 case value_t::number_integer: | |
5289 case value_t::number_unsigned: | |
5290 case value_t::number_float: | |
5291 case value_t::binary: | |
5292 case value_t::discarded: | |
5293 default: | |
5294 return empty_str; | |
5295 } | |
5296 } | |
5297 | |
5298 /// return value of the iterator | |
5299 typename IteratorType::reference value() const | |
5300 { | |
5301 return anchor.value(); | |
5302 } | |
5303 }; | |
5304 | |
5305 /// proxy class for the items() function | |
5306 template<typename IteratorType> class iteration_proxy | |
5307 { | |
5308 private: | |
5309 /// the container to iterate | |
5310 typename IteratorType::pointer container = nullptr; | |
5311 | |
5312 public: | |
5313 explicit iteration_proxy() = default; | |
5314 | |
5315 /// construct iteration proxy from a container | |
5316 explicit iteration_proxy(typename IteratorType::reference cont) noexcept | |
5317 : container(&cont) {} | |
5318 | |
5319 iteration_proxy(iteration_proxy const&) = default; | |
5320 iteration_proxy& operator=(iteration_proxy const&) = default; | |
5321 iteration_proxy(iteration_proxy&&) noexcept = default; | |
5322 iteration_proxy& operator=(iteration_proxy&&) noexcept = default; | |
5323 ~iteration_proxy() = default; | |
5324 | |
5325 /// return iterator begin (needed for range-based for) | |
5326 iteration_proxy_value<IteratorType> begin() const noexcept | |
5327 { | |
5328 return iteration_proxy_value<IteratorType>(container->begin()); | |
5329 } | |
5330 | |
5331 /// return iterator end (needed for range-based for) | |
5332 iteration_proxy_value<IteratorType> end() const noexcept | |
5333 { | |
5334 return iteration_proxy_value<IteratorType>(container->end()); | |
5335 } | |
5336 }; | |
5337 | |
5338 // Structured Bindings Support | |
5339 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | |
5340 // And see https://github.com/nlohmann/json/pull/1391 | |
5341 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> | |
5342 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) | |
5343 { | |
5344 return i.key(); | |
5345 } | |
5346 // Structured Bindings Support | |
5347 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | |
5348 // And see https://github.com/nlohmann/json/pull/1391 | |
5349 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> | |
5350 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) | |
5351 { | |
5352 return i.value(); | |
5353 } | |
5354 | |
5355 } // namespace detail | |
5356 NLOHMANN_JSON_NAMESPACE_END | |
5357 | |
5358 // The Addition to the STD Namespace is required to add | |
5359 // Structured Bindings Support to the iteration_proxy_value class | |
5360 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ | |
5361 // And see https://github.com/nlohmann/json/pull/1391 | |
5362 namespace std | |
5363 { | |
5364 | |
5365 #if defined(__clang__) | |
5366 // Fix: https://github.com/nlohmann/json/issues/1401 | |
5367 #pragma clang diagnostic push | |
5368 #pragma clang diagnostic ignored "-Wmismatched-tags" | |
5369 #endif | |
5370 template<typename IteratorType> | |
5371 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp) | |
5372 : public std::integral_constant<std::size_t, 2> {}; | |
5373 | |
5374 template<std::size_t N, typename IteratorType> | |
5375 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp) | |
5376 { | |
5377 public: | |
5378 using type = decltype( | |
5379 get<N>(std::declval < | |
5380 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); | |
5381 }; | |
5382 #if defined(__clang__) | |
5383 #pragma clang diagnostic pop | |
5384 #endif | |
5385 | |
5386 } // namespace std | |
5387 | |
5388 #if JSON_HAS_RANGES | |
5389 template <typename IteratorType> | |
5390 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; | |
5391 #endif | |
5392 | |
5393 // #include <nlohmann/detail/macro_scope.hpp> | |
5394 | |
5395 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
5396 | |
5397 // #include <nlohmann/detail/meta/std_fs.hpp> | |
5398 | |
5399 // #include <nlohmann/detail/meta/type_traits.hpp> | |
5400 | |
5401 // #include <nlohmann/detail/value_t.hpp> | |
5402 | |
5403 | |
5404 NLOHMANN_JSON_NAMESPACE_BEGIN | |
5405 namespace detail | |
5406 { | |
5407 | |
5408 ////////////////// | |
5409 // constructors // | |
5410 ////////////////// | |
5411 | |
5412 /* | |
5413 * Note all external_constructor<>::construct functions need to call | |
5414 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an | |
5415 * allocated value (e.g., a string). See bug issue | |
5416 * https://github.com/nlohmann/json/issues/2865 for more information. | |
5417 */ | |
5418 | |
5419 template<value_t> struct external_constructor; | |
5420 | |
5421 template<> | |
5422 struct external_constructor<value_t::boolean> | |
5423 { | |
5424 template<typename BasicJsonType> | |
5425 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept | |
5426 { | |
5427 j.m_data.m_value.destroy(j.m_data.m_type); | |
5428 j.m_data.m_type = value_t::boolean; | |
5429 j.m_data.m_value = b; | |
5430 j.assert_invariant(); | |
5431 } | |
5432 }; | |
5433 | |
5434 template<> | |
5435 struct external_constructor<value_t::string> | |
5436 { | |
5437 template<typename BasicJsonType> | |
5438 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) | |
5439 { | |
5440 j.m_data.m_value.destroy(j.m_data.m_type); | |
5441 j.m_data.m_type = value_t::string; | |
5442 j.m_data.m_value = s; | |
5443 j.assert_invariant(); | |
5444 } | |
5445 | |
5446 template<typename BasicJsonType> | |
5447 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) | |
5448 { | |
5449 j.m_data.m_value.destroy(j.m_data.m_type); | |
5450 j.m_data.m_type = value_t::string; | |
5451 j.m_data.m_value = std::move(s); | |
5452 j.assert_invariant(); | |
5453 } | |
5454 | |
5455 template < typename BasicJsonType, typename CompatibleStringType, | |
5456 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, | |
5457 int > = 0 > | |
5458 static void construct(BasicJsonType& j, const CompatibleStringType& str) | |
5459 { | |
5460 j.m_data.m_value.destroy(j.m_data.m_type); | |
5461 j.m_data.m_type = value_t::string; | |
5462 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); | |
5463 j.assert_invariant(); | |
5464 } | |
5465 }; | |
5466 | |
5467 template<> | |
5468 struct external_constructor<value_t::binary> | |
5469 { | |
5470 template<typename BasicJsonType> | |
5471 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) | |
5472 { | |
5473 j.m_data.m_value.destroy(j.m_data.m_type); | |
5474 j.m_data.m_type = value_t::binary; | |
5475 j.m_data.m_value = typename BasicJsonType::binary_t(b); | |
5476 j.assert_invariant(); | |
5477 } | |
5478 | |
5479 template<typename BasicJsonType> | |
5480 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) | |
5481 { | |
5482 j.m_data.m_value.destroy(j.m_data.m_type); | |
5483 j.m_data.m_type = value_t::binary; | |
5484 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); | |
5485 j.assert_invariant(); | |
5486 } | |
5487 }; | |
5488 | |
5489 template<> | |
5490 struct external_constructor<value_t::number_float> | |
5491 { | |
5492 template<typename BasicJsonType> | |
5493 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept | |
5494 { | |
5495 j.m_data.m_value.destroy(j.m_data.m_type); | |
5496 j.m_data.m_type = value_t::number_float; | |
5497 j.m_data.m_value = val; | |
5498 j.assert_invariant(); | |
5499 } | |
5500 }; | |
5501 | |
5502 template<> | |
5503 struct external_constructor<value_t::number_unsigned> | |
5504 { | |
5505 template<typename BasicJsonType> | |
5506 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept | |
5507 { | |
5508 j.m_data.m_value.destroy(j.m_data.m_type); | |
5509 j.m_data.m_type = value_t::number_unsigned; | |
5510 j.m_data.m_value = val; | |
5511 j.assert_invariant(); | |
5512 } | |
5513 }; | |
5514 | |
5515 template<> | |
5516 struct external_constructor<value_t::number_integer> | |
5517 { | |
5518 template<typename BasicJsonType> | |
5519 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept | |
5520 { | |
5521 j.m_data.m_value.destroy(j.m_data.m_type); | |
5522 j.m_data.m_type = value_t::number_integer; | |
5523 j.m_data.m_value = val; | |
5524 j.assert_invariant(); | |
5525 } | |
5526 }; | |
5527 | |
5528 template<> | |
5529 struct external_constructor<value_t::array> | |
5530 { | |
5531 template<typename BasicJsonType> | |
5532 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) | |
5533 { | |
5534 j.m_data.m_value.destroy(j.m_data.m_type); | |
5535 j.m_data.m_type = value_t::array; | |
5536 j.m_data.m_value = arr; | |
5537 j.set_parents(); | |
5538 j.assert_invariant(); | |
5539 } | |
5540 | |
5541 template<typename BasicJsonType> | |
5542 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) | |
5543 { | |
5544 j.m_data.m_value.destroy(j.m_data.m_type); | |
5545 j.m_data.m_type = value_t::array; | |
5546 j.m_data.m_value = std::move(arr); | |
5547 j.set_parents(); | |
5548 j.assert_invariant(); | |
5549 } | |
5550 | |
5551 template < typename BasicJsonType, typename CompatibleArrayType, | |
5552 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, | |
5553 int > = 0 > | |
5554 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) | |
5555 { | |
5556 using std::begin; | |
5557 using std::end; | |
5558 | |
5559 j.m_data.m_value.destroy(j.m_data.m_type); | |
5560 j.m_data.m_type = value_t::array; | |
5561 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); | |
5562 j.set_parents(); | |
5563 j.assert_invariant(); | |
5564 } | |
5565 | |
5566 template<typename BasicJsonType> | |
5567 static void construct(BasicJsonType& j, const std::vector<bool>& arr) | |
5568 { | |
5569 j.m_data.m_value.destroy(j.m_data.m_type); | |
5570 j.m_data.m_type = value_t::array; | |
5571 j.m_data.m_value = value_t::array; | |
5572 j.m_data.m_value.array->reserve(arr.size()); | |
5573 for (const bool x : arr) | |
5574 { | |
5575 j.m_data.m_value.array->push_back(x); | |
5576 j.set_parent(j.m_data.m_value.array->back()); | |
5577 } | |
5578 j.assert_invariant(); | |
5579 } | |
5580 | |
5581 template<typename BasicJsonType, typename T, | |
5582 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> | |
5583 static void construct(BasicJsonType& j, const std::valarray<T>& arr) | |
5584 { | |
5585 j.m_data.m_value.destroy(j.m_data.m_type); | |
5586 j.m_data.m_type = value_t::array; | |
5587 j.m_data.m_value = value_t::array; | |
5588 j.m_data.m_value.array->resize(arr.size()); | |
5589 if (arr.size() > 0) | |
5590 { | |
5591 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); | |
5592 } | |
5593 j.set_parents(); | |
5594 j.assert_invariant(); | |
5595 } | |
5596 }; | |
5597 | |
5598 template<> | |
5599 struct external_constructor<value_t::object> | |
5600 { | |
5601 template<typename BasicJsonType> | |
5602 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) | |
5603 { | |
5604 j.m_data.m_value.destroy(j.m_data.m_type); | |
5605 j.m_data.m_type = value_t::object; | |
5606 j.m_data.m_value = obj; | |
5607 j.set_parents(); | |
5608 j.assert_invariant(); | |
5609 } | |
5610 | |
5611 template<typename BasicJsonType> | |
5612 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) | |
5613 { | |
5614 j.m_data.m_value.destroy(j.m_data.m_type); | |
5615 j.m_data.m_type = value_t::object; | |
5616 j.m_data.m_value = std::move(obj); | |
5617 j.set_parents(); | |
5618 j.assert_invariant(); | |
5619 } | |
5620 | |
5621 template < typename BasicJsonType, typename CompatibleObjectType, | |
5622 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > | |
5623 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) | |
5624 { | |
5625 using std::begin; | |
5626 using std::end; | |
5627 | |
5628 j.m_data.m_value.destroy(j.m_data.m_type); | |
5629 j.m_data.m_type = value_t::object; | |
5630 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); | |
5631 j.set_parents(); | |
5632 j.assert_invariant(); | |
5633 } | |
5634 }; | |
5635 | |
5636 ///////////// | |
5637 // to_json // | |
5638 ///////////// | |
5639 | |
5640 template<typename BasicJsonType, typename T, | |
5641 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> | |
5642 inline void to_json(BasicJsonType& j, T b) noexcept | |
5643 { | |
5644 external_constructor<value_t::boolean>::construct(j, b); | |
5645 } | |
5646 | |
5647 template < typename BasicJsonType, typename BoolRef, | |
5648 enable_if_t < | |
5649 ((std::is_same<std::vector<bool>::reference, BoolRef>::value | |
5650 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) | |
5651 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value | |
5652 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, | |
5653 typename BasicJsonType::boolean_t >::value)) | |
5654 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > | |
5655 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept | |
5656 { | |
5657 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); | |
5658 } | |
5659 | |
5660 template<typename BasicJsonType, typename CompatibleString, | |
5661 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> | |
5662 inline void to_json(BasicJsonType& j, const CompatibleString& s) | |
5663 { | |
5664 external_constructor<value_t::string>::construct(j, s); | |
5665 } | |
5666 | |
5667 template<typename BasicJsonType> | |
5668 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) | |
5669 { | |
5670 external_constructor<value_t::string>::construct(j, std::move(s)); | |
5671 } | |
5672 | |
5673 template<typename BasicJsonType, typename FloatType, | |
5674 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> | |
5675 inline void to_json(BasicJsonType& j, FloatType val) noexcept | |
5676 { | |
5677 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); | |
5678 } | |
5679 | |
5680 template<typename BasicJsonType, typename CompatibleNumberUnsignedType, | |
5681 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> | |
5682 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept | |
5683 { | |
5684 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); | |
5685 } | |
5686 | |
5687 template<typename BasicJsonType, typename CompatibleNumberIntegerType, | |
5688 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> | |
5689 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept | |
5690 { | |
5691 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); | |
5692 } | |
5693 | |
5694 #if !JSON_DISABLE_ENUM_SERIALIZATION | |
5695 template<typename BasicJsonType, typename EnumType, | |
5696 enable_if_t<std::is_enum<EnumType>::value, int> = 0> | |
5697 inline void to_json(BasicJsonType& j, EnumType e) noexcept | |
5698 { | |
5699 using underlying_type = typename std::underlying_type<EnumType>::type; | |
5700 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); | |
5701 } | |
5702 #endif // JSON_DISABLE_ENUM_SERIALIZATION | |
5703 | |
5704 template<typename BasicJsonType> | |
5705 inline void to_json(BasicJsonType& j, const std::vector<bool>& e) | |
5706 { | |
5707 external_constructor<value_t::array>::construct(j, e); | |
5708 } | |
5709 | |
5710 template < typename BasicJsonType, typename CompatibleArrayType, | |
5711 enable_if_t < is_compatible_array_type<BasicJsonType, | |
5712 CompatibleArrayType>::value&& | |
5713 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& | |
5714 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& | |
5715 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& | |
5716 !is_basic_json<CompatibleArrayType>::value, | |
5717 int > = 0 > | |
5718 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) | |
5719 { | |
5720 external_constructor<value_t::array>::construct(j, arr); | |
5721 } | |
5722 | |
5723 template<typename BasicJsonType> | |
5724 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) | |
5725 { | |
5726 external_constructor<value_t::binary>::construct(j, bin); | |
5727 } | |
5728 | |
5729 template<typename BasicJsonType, typename T, | |
5730 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> | |
5731 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) | |
5732 { | |
5733 external_constructor<value_t::array>::construct(j, std::move(arr)); | |
5734 } | |
5735 | |
5736 template<typename BasicJsonType> | |
5737 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) | |
5738 { | |
5739 external_constructor<value_t::array>::construct(j, std::move(arr)); | |
5740 } | |
5741 | |
5742 template < typename BasicJsonType, typename CompatibleObjectType, | |
5743 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > | |
5744 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) | |
5745 { | |
5746 external_constructor<value_t::object>::construct(j, obj); | |
5747 } | |
5748 | |
5749 template<typename BasicJsonType> | |
5750 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) | |
5751 { | |
5752 external_constructor<value_t::object>::construct(j, std::move(obj)); | |
5753 } | |
5754 | |
5755 template < | |
5756 typename BasicJsonType, typename T, std::size_t N, | |
5757 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, | |
5758 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
5759 int > = 0 > | |
5760 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
5761 { | |
5762 external_constructor<value_t::array>::construct(j, arr); | |
5763 } | |
5764 | |
5765 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > | |
5766 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) | |
5767 { | |
5768 j = { p.first, p.second }; | |
5769 } | |
5770 | |
5771 // for https://github.com/nlohmann/json/pull/1134 | |
5772 template<typename BasicJsonType, typename T, | |
5773 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> | |
5774 inline void to_json(BasicJsonType& j, const T& b) | |
5775 { | |
5776 j = { {b.key(), b.value()} }; | |
5777 } | |
5778 | |
5779 template<typename BasicJsonType, typename Tuple, std::size_t... Idx> | |
5780 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) | |
5781 { | |
5782 j = { std::get<Idx>(t)... }; | |
5783 } | |
5784 | |
5785 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> | |
5786 inline void to_json(BasicJsonType& j, const T& t) | |
5787 { | |
5788 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); | |
5789 } | |
5790 | |
5791 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
5792 template<typename BasicJsonType> | |
5793 inline void to_json(BasicJsonType& j, const std_fs::path& p) | |
5794 { | |
5795 j = p.string(); | |
5796 } | |
5797 #endif | |
5798 | |
5799 struct to_json_fn | |
5800 { | |
5801 template<typename BasicJsonType, typename T> | |
5802 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) | |
5803 -> decltype(to_json(j, std::forward<T>(val)), void()) | |
5804 { | |
5805 return to_json(j, std::forward<T>(val)); | |
5806 } | |
5807 }; | |
5808 } // namespace detail | |
5809 | |
5810 #ifndef JSON_HAS_CPP_17 | |
5811 /// namespace to hold default `to_json` function | |
5812 /// to see why this is required: | |
5813 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html | |
5814 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) | |
5815 { | |
5816 #endif | |
5817 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) | |
5818 detail::static_const<detail::to_json_fn>::value; | |
5819 #ifndef JSON_HAS_CPP_17 | |
5820 } // namespace | |
5821 #endif | |
5822 | |
5823 NLOHMANN_JSON_NAMESPACE_END | |
5824 | |
5825 // #include <nlohmann/detail/meta/identity_tag.hpp> | |
5826 | |
5827 | |
5828 NLOHMANN_JSON_NAMESPACE_BEGIN | |
5829 | |
5830 /// @sa https://json.nlohmann.me/api/adl_serializer/ | |
5831 template<typename ValueType, typename> | |
5832 struct adl_serializer | |
5833 { | |
5834 /// @brief convert a JSON value to any value type | |
5835 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ | |
5836 template<typename BasicJsonType, typename TargetType = ValueType> | |
5837 static auto from_json(BasicJsonType && j, TargetType& val) noexcept( | |
5838 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) | |
5839 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) | |
5840 { | |
5841 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); | |
5842 } | |
5843 | |
5844 /// @brief convert a JSON value to any value type | |
5845 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ | |
5846 template<typename BasicJsonType, typename TargetType = ValueType> | |
5847 static auto from_json(BasicJsonType && j) noexcept( | |
5848 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))) | |
5849 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})) | |
5850 { | |
5851 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}); | |
5852 } | |
5853 | |
5854 /// @brief convert any value type to a JSON value | |
5855 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ | |
5856 template<typename BasicJsonType, typename TargetType = ValueType> | |
5857 static auto to_json(BasicJsonType& j, TargetType && val) noexcept( | |
5858 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val)))) | |
5859 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) | |
5860 { | |
5861 ::nlohmann::to_json(j, std::forward<TargetType>(val)); | |
5862 } | |
5863 }; | |
5864 | |
5865 NLOHMANN_JSON_NAMESPACE_END | |
5866 | |
5867 // #include <nlohmann/byte_container_with_subtype.hpp> | |
5868 // __ _____ _____ _____ | |
5869 // __| | __| | | | JSON for Modern C++ | |
5870 // | | |__ | | | | | | version 3.11.3 | |
5871 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
5872 // | |
5873 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
5874 // SPDX-License-Identifier: MIT | |
5875 | |
5876 | |
5877 | |
5878 #include <cstdint> // uint8_t, uint64_t | |
5879 #include <tuple> // tie | |
5880 #include <utility> // move | |
5881 | |
5882 // #include <nlohmann/detail/abi_macros.hpp> | |
5883 | |
5884 | |
5885 NLOHMANN_JSON_NAMESPACE_BEGIN | |
5886 | |
5887 /// @brief an internal type for a backed binary type | |
5888 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ | |
5889 template<typename BinaryType> | |
5890 class byte_container_with_subtype : public BinaryType | |
5891 { | |
5892 public: | |
5893 using container_type = BinaryType; | |
5894 using subtype_type = std::uint64_t; | |
5895 | |
5896 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ | |
5897 byte_container_with_subtype() noexcept(noexcept(container_type())) | |
5898 : container_type() | |
5899 {} | |
5900 | |
5901 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ | |
5902 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) | |
5903 : container_type(b) | |
5904 {} | |
5905 | |
5906 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ | |
5907 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) | |
5908 : container_type(std::move(b)) | |
5909 {} | |
5910 | |
5911 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ | |
5912 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) | |
5913 : container_type(b) | |
5914 , m_subtype(subtype_) | |
5915 , m_has_subtype(true) | |
5916 {} | |
5917 | |
5918 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ | |
5919 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) | |
5920 : container_type(std::move(b)) | |
5921 , m_subtype(subtype_) | |
5922 , m_has_subtype(true) | |
5923 {} | |
5924 | |
5925 bool operator==(const byte_container_with_subtype& rhs) const | |
5926 { | |
5927 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) == | |
5928 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype); | |
5929 } | |
5930 | |
5931 bool operator!=(const byte_container_with_subtype& rhs) const | |
5932 { | |
5933 return !(rhs == *this); | |
5934 } | |
5935 | |
5936 /// @brief sets the binary subtype | |
5937 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ | |
5938 void set_subtype(subtype_type subtype_) noexcept | |
5939 { | |
5940 m_subtype = subtype_; | |
5941 m_has_subtype = true; | |
5942 } | |
5943 | |
5944 /// @brief return the binary subtype | |
5945 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ | |
5946 constexpr subtype_type subtype() const noexcept | |
5947 { | |
5948 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1); | |
5949 } | |
5950 | |
5951 /// @brief return whether the value has a subtype | |
5952 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ | |
5953 constexpr bool has_subtype() const noexcept | |
5954 { | |
5955 return m_has_subtype; | |
5956 } | |
5957 | |
5958 /// @brief clears the binary subtype | |
5959 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ | |
5960 void clear_subtype() noexcept | |
5961 { | |
5962 m_subtype = 0; | |
5963 m_has_subtype = false; | |
5964 } | |
5965 | |
5966 private: | |
5967 subtype_type m_subtype = 0; | |
5968 bool m_has_subtype = false; | |
5969 }; | |
5970 | |
5971 NLOHMANN_JSON_NAMESPACE_END | |
5972 | |
5973 // #include <nlohmann/detail/conversions/from_json.hpp> | |
5974 | |
5975 // #include <nlohmann/detail/conversions/to_json.hpp> | |
5976 | |
5977 // #include <nlohmann/detail/exceptions.hpp> | |
5978 | |
5979 // #include <nlohmann/detail/hash.hpp> | |
5980 // __ _____ _____ _____ | |
5981 // __| | __| | | | JSON for Modern C++ | |
5982 // | | |__ | | | | | | version 3.11.3 | |
5983 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
5984 // | |
5985 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
5986 // SPDX-License-Identifier: MIT | |
5987 | |
5988 | |
5989 | |
5990 #include <cstdint> // uint8_t | |
5991 #include <cstddef> // size_t | |
5992 #include <functional> // hash | |
5993 | |
5994 // #include <nlohmann/detail/abi_macros.hpp> | |
5995 | |
5996 // #include <nlohmann/detail/value_t.hpp> | |
5997 | |
5998 | |
5999 NLOHMANN_JSON_NAMESPACE_BEGIN | |
6000 namespace detail | |
6001 { | |
6002 | |
6003 // boost::hash_combine | |
6004 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept | |
6005 { | |
6006 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); | |
6007 return seed; | |
6008 } | |
6009 | |
6010 /*! | |
6011 @brief hash a JSON value | |
6012 | |
6013 The hash function tries to rely on std::hash where possible. Furthermore, the | |
6014 type of the JSON value is taken into account to have different hash values for | |
6015 null, 0, 0U, and false, etc. | |
6016 | |
6017 @tparam BasicJsonType basic_json specialization | |
6018 @param j JSON value to hash | |
6019 @return hash value of j | |
6020 */ | |
6021 template<typename BasicJsonType> | |
6022 std::size_t hash(const BasicJsonType& j) | |
6023 { | |
6024 using string_t = typename BasicJsonType::string_t; | |
6025 using number_integer_t = typename BasicJsonType::number_integer_t; | |
6026 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
6027 using number_float_t = typename BasicJsonType::number_float_t; | |
6028 | |
6029 const auto type = static_cast<std::size_t>(j.type()); | |
6030 switch (j.type()) | |
6031 { | |
6032 case BasicJsonType::value_t::null: | |
6033 case BasicJsonType::value_t::discarded: | |
6034 { | |
6035 return combine(type, 0); | |
6036 } | |
6037 | |
6038 case BasicJsonType::value_t::object: | |
6039 { | |
6040 auto seed = combine(type, j.size()); | |
6041 for (const auto& element : j.items()) | |
6042 { | |
6043 const auto h = std::hash<string_t> {}(element.key()); | |
6044 seed = combine(seed, h); | |
6045 seed = combine(seed, hash(element.value())); | |
6046 } | |
6047 return seed; | |
6048 } | |
6049 | |
6050 case BasicJsonType::value_t::array: | |
6051 { | |
6052 auto seed = combine(type, j.size()); | |
6053 for (const auto& element : j) | |
6054 { | |
6055 seed = combine(seed, hash(element)); | |
6056 } | |
6057 return seed; | |
6058 } | |
6059 | |
6060 case BasicJsonType::value_t::string: | |
6061 { | |
6062 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); | |
6063 return combine(type, h); | |
6064 } | |
6065 | |
6066 case BasicJsonType::value_t::boolean: | |
6067 { | |
6068 const auto h = std::hash<bool> {}(j.template get<bool>()); | |
6069 return combine(type, h); | |
6070 } | |
6071 | |
6072 case BasicJsonType::value_t::number_integer: | |
6073 { | |
6074 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); | |
6075 return combine(type, h); | |
6076 } | |
6077 | |
6078 case BasicJsonType::value_t::number_unsigned: | |
6079 { | |
6080 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); | |
6081 return combine(type, h); | |
6082 } | |
6083 | |
6084 case BasicJsonType::value_t::number_float: | |
6085 { | |
6086 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); | |
6087 return combine(type, h); | |
6088 } | |
6089 | |
6090 case BasicJsonType::value_t::binary: | |
6091 { | |
6092 auto seed = combine(type, j.get_binary().size()); | |
6093 const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); | |
6094 seed = combine(seed, h); | |
6095 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); | |
6096 for (const auto byte : j.get_binary()) | |
6097 { | |
6098 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); | |
6099 } | |
6100 return seed; | |
6101 } | |
6102 | |
6103 default: // LCOV_EXCL_LINE | |
6104 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
6105 return 0; // LCOV_EXCL_LINE | |
6106 } | |
6107 } | |
6108 | |
6109 } // namespace detail | |
6110 NLOHMANN_JSON_NAMESPACE_END | |
6111 | |
6112 // #include <nlohmann/detail/input/binary_reader.hpp> | |
6113 // __ _____ _____ _____ | |
6114 // __| | __| | | | JSON for Modern C++ | |
6115 // | | |__ | | | | | | version 3.11.3 | |
6116 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
6117 // | |
6118 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
6119 // SPDX-License-Identifier: MIT | |
6120 | |
6121 | |
6122 | |
6123 #include <algorithm> // generate_n | |
6124 #include <array> // array | |
6125 #include <cmath> // ldexp | |
6126 #include <cstddef> // size_t | |
6127 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t | |
6128 #include <cstdio> // snprintf | |
6129 #include <cstring> // memcpy | |
6130 #include <iterator> // back_inserter | |
6131 #include <limits> // numeric_limits | |
6132 #include <string> // char_traits, string | |
6133 #include <utility> // make_pair, move | |
6134 #include <vector> // vector | |
6135 | |
6136 // #include <nlohmann/detail/exceptions.hpp> | |
6137 | |
6138 // #include <nlohmann/detail/input/input_adapters.hpp> | |
6139 // __ _____ _____ _____ | |
6140 // __| | __| | | | JSON for Modern C++ | |
6141 // | | |__ | | | | | | version 3.11.3 | |
6142 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
6143 // | |
6144 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
6145 // SPDX-License-Identifier: MIT | |
6146 | |
6147 | |
6148 | |
6149 #include <array> // array | |
6150 #include <cstddef> // size_t | |
6151 #include <cstring> // strlen | |
6152 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next | |
6153 #include <memory> // shared_ptr, make_shared, addressof | |
6154 #include <numeric> // accumulate | |
6155 #include <string> // string, char_traits | |
6156 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer | |
6157 #include <utility> // pair, declval | |
6158 | |
6159 #ifndef JSON_NO_IO | |
6160 #include <cstdio> // FILE * | |
6161 #include <istream> // istream | |
6162 #endif // JSON_NO_IO | |
6163 | |
6164 // #include <nlohmann/detail/iterators/iterator_traits.hpp> | |
6165 | |
6166 // #include <nlohmann/detail/macro_scope.hpp> | |
6167 | |
6168 // #include <nlohmann/detail/meta/type_traits.hpp> | |
6169 | |
6170 | |
6171 NLOHMANN_JSON_NAMESPACE_BEGIN | |
6172 namespace detail | |
6173 { | |
6174 | |
6175 /// the supported input formats | |
6176 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; | |
6177 | |
6178 //////////////////// | |
6179 // input adapters // | |
6180 //////////////////// | |
6181 | |
6182 #ifndef JSON_NO_IO | |
6183 /*! | |
6184 Input adapter for stdio file access. This adapter read only 1 byte and do not use any | |
6185 buffer. This adapter is a very low level adapter. | |
6186 */ | |
6187 class file_input_adapter | |
6188 { | |
6189 public: | |
6190 using char_type = char; | |
6191 | |
6192 JSON_HEDLEY_NON_NULL(2) | |
6193 explicit file_input_adapter(std::FILE* f) noexcept | |
6194 : m_file(f) | |
6195 { | |
6196 JSON_ASSERT(m_file != nullptr); | |
6197 } | |
6198 | |
6199 // make class move-only | |
6200 file_input_adapter(const file_input_adapter&) = delete; | |
6201 file_input_adapter(file_input_adapter&&) noexcept = default; | |
6202 file_input_adapter& operator=(const file_input_adapter&) = delete; | |
6203 file_input_adapter& operator=(file_input_adapter&&) = delete; | |
6204 ~file_input_adapter() = default; | |
6205 | |
6206 std::char_traits<char>::int_type get_character() noexcept | |
6207 { | |
6208 return std::fgetc(m_file); | |
6209 } | |
6210 | |
6211 private: | |
6212 /// the file pointer to read from | |
6213 std::FILE* m_file; | |
6214 }; | |
6215 | |
6216 /*! | |
6217 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at | |
6218 beginning of input. Does not support changing the underlying std::streambuf | |
6219 in mid-input. Maintains underlying std::istream and std::streambuf to support | |
6220 subsequent use of standard std::istream operations to process any input | |
6221 characters following those used in parsing the JSON input. Clears the | |
6222 std::istream flags; any input errors (e.g., EOF) will be detected by the first | |
6223 subsequent call for input from the std::istream. | |
6224 */ | |
6225 class input_stream_adapter | |
6226 { | |
6227 public: | |
6228 using char_type = char; | |
6229 | |
6230 ~input_stream_adapter() | |
6231 { | |
6232 // clear stream flags; we use underlying streambuf I/O, do not | |
6233 // maintain ifstream flags, except eof | |
6234 if (is != nullptr) | |
6235 { | |
6236 is->clear(is->rdstate() & std::ios::eofbit); | |
6237 } | |
6238 } | |
6239 | |
6240 explicit input_stream_adapter(std::istream& i) | |
6241 : is(&i), sb(i.rdbuf()) | |
6242 {} | |
6243 | |
6244 // delete because of pointer members | |
6245 input_stream_adapter(const input_stream_adapter&) = delete; | |
6246 input_stream_adapter& operator=(input_stream_adapter&) = delete; | |
6247 input_stream_adapter& operator=(input_stream_adapter&&) = delete; | |
6248 | |
6249 input_stream_adapter(input_stream_adapter&& rhs) noexcept | |
6250 : is(rhs.is), sb(rhs.sb) | |
6251 { | |
6252 rhs.is = nullptr; | |
6253 rhs.sb = nullptr; | |
6254 } | |
6255 | |
6256 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to | |
6257 // ensure that std::char_traits<char>::eof() and the character 0xFF do not | |
6258 // end up as the same value, e.g. 0xFFFFFFFF. | |
6259 std::char_traits<char>::int_type get_character() | |
6260 { | |
6261 auto res = sb->sbumpc(); | |
6262 // set eof manually, as we don't use the istream interface. | |
6263 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) | |
6264 { | |
6265 is->clear(is->rdstate() | std::ios::eofbit); | |
6266 } | |
6267 return res; | |
6268 } | |
6269 | |
6270 private: | |
6271 /// the associated input stream | |
6272 std::istream* is = nullptr; | |
6273 std::streambuf* sb = nullptr; | |
6274 }; | |
6275 #endif // JSON_NO_IO | |
6276 | |
6277 // General-purpose iterator-based adapter. It might not be as fast as | |
6278 // theoretically possible for some containers, but it is extremely versatile. | |
6279 template<typename IteratorType> | |
6280 class iterator_input_adapter | |
6281 { | |
6282 public: | |
6283 using char_type = typename std::iterator_traits<IteratorType>::value_type; | |
6284 | |
6285 iterator_input_adapter(IteratorType first, IteratorType last) | |
6286 : current(std::move(first)), end(std::move(last)) | |
6287 {} | |
6288 | |
6289 typename char_traits<char_type>::int_type get_character() | |
6290 { | |
6291 if (JSON_HEDLEY_LIKELY(current != end)) | |
6292 { | |
6293 auto result = char_traits<char_type>::to_int_type(*current); | |
6294 std::advance(current, 1); | |
6295 return result; | |
6296 } | |
6297 | |
6298 return char_traits<char_type>::eof(); | |
6299 } | |
6300 | |
6301 private: | |
6302 IteratorType current; | |
6303 IteratorType end; | |
6304 | |
6305 template<typename BaseInputAdapter, size_t T> | |
6306 friend struct wide_string_input_helper; | |
6307 | |
6308 bool empty() const | |
6309 { | |
6310 return current == end; | |
6311 } | |
6312 }; | |
6313 | |
6314 template<typename BaseInputAdapter, size_t T> | |
6315 struct wide_string_input_helper; | |
6316 | |
6317 template<typename BaseInputAdapter> | |
6318 struct wide_string_input_helper<BaseInputAdapter, 4> | |
6319 { | |
6320 // UTF-32 | |
6321 static void fill_buffer(BaseInputAdapter& input, | |
6322 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, | |
6323 size_t& utf8_bytes_index, | |
6324 size_t& utf8_bytes_filled) | |
6325 { | |
6326 utf8_bytes_index = 0; | |
6327 | |
6328 if (JSON_HEDLEY_UNLIKELY(input.empty())) | |
6329 { | |
6330 utf8_bytes[0] = std::char_traits<char>::eof(); | |
6331 utf8_bytes_filled = 1; | |
6332 } | |
6333 else | |
6334 { | |
6335 // get the current character | |
6336 const auto wc = input.get_character(); | |
6337 | |
6338 // UTF-32 to UTF-8 encoding | |
6339 if (wc < 0x80) | |
6340 { | |
6341 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | |
6342 utf8_bytes_filled = 1; | |
6343 } | |
6344 else if (wc <= 0x7FF) | |
6345 { | |
6346 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); | |
6347 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | |
6348 utf8_bytes_filled = 2; | |
6349 } | |
6350 else if (wc <= 0xFFFF) | |
6351 { | |
6352 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); | |
6353 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | |
6354 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | |
6355 utf8_bytes_filled = 3; | |
6356 } | |
6357 else if (wc <= 0x10FFFF) | |
6358 { | |
6359 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); | |
6360 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); | |
6361 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | |
6362 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | |
6363 utf8_bytes_filled = 4; | |
6364 } | |
6365 else | |
6366 { | |
6367 // unknown character | |
6368 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | |
6369 utf8_bytes_filled = 1; | |
6370 } | |
6371 } | |
6372 } | |
6373 }; | |
6374 | |
6375 template<typename BaseInputAdapter> | |
6376 struct wide_string_input_helper<BaseInputAdapter, 2> | |
6377 { | |
6378 // UTF-16 | |
6379 static void fill_buffer(BaseInputAdapter& input, | |
6380 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, | |
6381 size_t& utf8_bytes_index, | |
6382 size_t& utf8_bytes_filled) | |
6383 { | |
6384 utf8_bytes_index = 0; | |
6385 | |
6386 if (JSON_HEDLEY_UNLIKELY(input.empty())) | |
6387 { | |
6388 utf8_bytes[0] = std::char_traits<char>::eof(); | |
6389 utf8_bytes_filled = 1; | |
6390 } | |
6391 else | |
6392 { | |
6393 // get the current character | |
6394 const auto wc = input.get_character(); | |
6395 | |
6396 // UTF-16 to UTF-8 encoding | |
6397 if (wc < 0x80) | |
6398 { | |
6399 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | |
6400 utf8_bytes_filled = 1; | |
6401 } | |
6402 else if (wc <= 0x7FF) | |
6403 { | |
6404 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); | |
6405 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | |
6406 utf8_bytes_filled = 2; | |
6407 } | |
6408 else if (0xD800 > wc || wc >= 0xE000) | |
6409 { | |
6410 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); | |
6411 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); | |
6412 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); | |
6413 utf8_bytes_filled = 3; | |
6414 } | |
6415 else | |
6416 { | |
6417 if (JSON_HEDLEY_UNLIKELY(!input.empty())) | |
6418 { | |
6419 const auto wc2 = static_cast<unsigned int>(input.get_character()); | |
6420 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); | |
6421 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); | |
6422 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); | |
6423 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); | |
6424 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); | |
6425 utf8_bytes_filled = 4; | |
6426 } | |
6427 else | |
6428 { | |
6429 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); | |
6430 utf8_bytes_filled = 1; | |
6431 } | |
6432 } | |
6433 } | |
6434 } | |
6435 }; | |
6436 | |
6437 // Wraps another input adapter to convert wide character types into individual bytes. | |
6438 template<typename BaseInputAdapter, typename WideCharType> | |
6439 class wide_string_input_adapter | |
6440 { | |
6441 public: | |
6442 using char_type = char; | |
6443 | |
6444 wide_string_input_adapter(BaseInputAdapter base) | |
6445 : base_adapter(base) {} | |
6446 | |
6447 typename std::char_traits<char>::int_type get_character() noexcept | |
6448 { | |
6449 // check if buffer needs to be filled | |
6450 if (utf8_bytes_index == utf8_bytes_filled) | |
6451 { | |
6452 fill_buffer<sizeof(WideCharType)>(); | |
6453 | |
6454 JSON_ASSERT(utf8_bytes_filled > 0); | |
6455 JSON_ASSERT(utf8_bytes_index == 0); | |
6456 } | |
6457 | |
6458 // use buffer | |
6459 JSON_ASSERT(utf8_bytes_filled > 0); | |
6460 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); | |
6461 return utf8_bytes[utf8_bytes_index++]; | |
6462 } | |
6463 | |
6464 private: | |
6465 BaseInputAdapter base_adapter; | |
6466 | |
6467 template<size_t T> | |
6468 void fill_buffer() | |
6469 { | |
6470 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); | |
6471 } | |
6472 | |
6473 /// a buffer for UTF-8 bytes | |
6474 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; | |
6475 | |
6476 /// index to the utf8_codes array for the next valid byte | |
6477 std::size_t utf8_bytes_index = 0; | |
6478 /// number of valid bytes in the utf8_codes array | |
6479 std::size_t utf8_bytes_filled = 0; | |
6480 }; | |
6481 | |
6482 template<typename IteratorType, typename Enable = void> | |
6483 struct iterator_input_adapter_factory | |
6484 { | |
6485 using iterator_type = IteratorType; | |
6486 using char_type = typename std::iterator_traits<iterator_type>::value_type; | |
6487 using adapter_type = iterator_input_adapter<iterator_type>; | |
6488 | |
6489 static adapter_type create(IteratorType first, IteratorType last) | |
6490 { | |
6491 return adapter_type(std::move(first), std::move(last)); | |
6492 } | |
6493 }; | |
6494 | |
6495 template<typename T> | |
6496 struct is_iterator_of_multibyte | |
6497 { | |
6498 using value_type = typename std::iterator_traits<T>::value_type; | |
6499 enum | |
6500 { | |
6501 value = sizeof(value_type) > 1 | |
6502 }; | |
6503 }; | |
6504 | |
6505 template<typename IteratorType> | |
6506 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> | |
6507 { | |
6508 using iterator_type = IteratorType; | |
6509 using char_type = typename std::iterator_traits<iterator_type>::value_type; | |
6510 using base_adapter_type = iterator_input_adapter<iterator_type>; | |
6511 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; | |
6512 | |
6513 static adapter_type create(IteratorType first, IteratorType last) | |
6514 { | |
6515 return adapter_type(base_adapter_type(std::move(first), std::move(last))); | |
6516 } | |
6517 }; | |
6518 | |
6519 // General purpose iterator-based input | |
6520 template<typename IteratorType> | |
6521 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) | |
6522 { | |
6523 using factory_type = iterator_input_adapter_factory<IteratorType>; | |
6524 return factory_type::create(first, last); | |
6525 } | |
6526 | |
6527 // Convenience shorthand from container to iterator | |
6528 // Enables ADL on begin(container) and end(container) | |
6529 // Encloses the using declarations in namespace for not to leak them to outside scope | |
6530 | |
6531 namespace container_input_adapter_factory_impl | |
6532 { | |
6533 | |
6534 using std::begin; | |
6535 using std::end; | |
6536 | |
6537 template<typename ContainerType, typename Enable = void> | |
6538 struct container_input_adapter_factory {}; | |
6539 | |
6540 template<typename ContainerType> | |
6541 struct container_input_adapter_factory< ContainerType, | |
6542 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> | |
6543 { | |
6544 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); | |
6545 | |
6546 static adapter_type create(const ContainerType& container) | |
6547 { | |
6548 return input_adapter(begin(container), end(container)); | |
6549 } | |
6550 }; | |
6551 | |
6552 } // namespace container_input_adapter_factory_impl | |
6553 | |
6554 template<typename ContainerType> | |
6555 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) | |
6556 { | |
6557 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); | |
6558 } | |
6559 | |
6560 #ifndef JSON_NO_IO | |
6561 // Special cases with fast paths | |
6562 inline file_input_adapter input_adapter(std::FILE* file) | |
6563 { | |
6564 return file_input_adapter(file); | |
6565 } | |
6566 | |
6567 inline input_stream_adapter input_adapter(std::istream& stream) | |
6568 { | |
6569 return input_stream_adapter(stream); | |
6570 } | |
6571 | |
6572 inline input_stream_adapter input_adapter(std::istream&& stream) | |
6573 { | |
6574 return input_stream_adapter(stream); | |
6575 } | |
6576 #endif // JSON_NO_IO | |
6577 | |
6578 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); | |
6579 | |
6580 // Null-delimited strings, and the like. | |
6581 template < typename CharT, | |
6582 typename std::enable_if < | |
6583 std::is_pointer<CharT>::value&& | |
6584 !std::is_array<CharT>::value&& | |
6585 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& | |
6586 sizeof(typename std::remove_pointer<CharT>::type) == 1, | |
6587 int >::type = 0 > | |
6588 contiguous_bytes_input_adapter input_adapter(CharT b) | |
6589 { | |
6590 auto length = std::strlen(reinterpret_cast<const char*>(b)); | |
6591 const auto* ptr = reinterpret_cast<const char*>(b); | |
6592 return input_adapter(ptr, ptr + length); | |
6593 } | |
6594 | |
6595 template<typename T, std::size_t N> | |
6596 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
6597 { | |
6598 return input_adapter(array, array + N); | |
6599 } | |
6600 | |
6601 // This class only handles inputs of input_buffer_adapter type. | |
6602 // It's required so that expressions like {ptr, len} can be implicitly cast | |
6603 // to the correct adapter. | |
6604 class span_input_adapter | |
6605 { | |
6606 public: | |
6607 template < typename CharT, | |
6608 typename std::enable_if < | |
6609 std::is_pointer<CharT>::value&& | |
6610 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& | |
6611 sizeof(typename std::remove_pointer<CharT>::type) == 1, | |
6612 int >::type = 0 > | |
6613 span_input_adapter(CharT b, std::size_t l) | |
6614 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} | |
6615 | |
6616 template<class IteratorType, | |
6617 typename std::enable_if< | |
6618 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, | |
6619 int>::type = 0> | |
6620 span_input_adapter(IteratorType first, IteratorType last) | |
6621 : ia(input_adapter(first, last)) {} | |
6622 | |
6623 contiguous_bytes_input_adapter&& get() | |
6624 { | |
6625 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) | |
6626 } | |
6627 | |
6628 private: | |
6629 contiguous_bytes_input_adapter ia; | |
6630 }; | |
6631 | |
6632 } // namespace detail | |
6633 NLOHMANN_JSON_NAMESPACE_END | |
6634 | |
6635 // #include <nlohmann/detail/input/json_sax.hpp> | |
6636 // __ _____ _____ _____ | |
6637 // __| | __| | | | JSON for Modern C++ | |
6638 // | | |__ | | | | | | version 3.11.3 | |
6639 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
6640 // | |
6641 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
6642 // SPDX-License-Identifier: MIT | |
6643 | |
6644 | |
6645 | |
6646 #include <cstddef> | |
6647 #include <string> // string | |
6648 #include <utility> // move | |
6649 #include <vector> // vector | |
6650 | |
6651 // #include <nlohmann/detail/exceptions.hpp> | |
6652 | |
6653 // #include <nlohmann/detail/macro_scope.hpp> | |
6654 | |
6655 // #include <nlohmann/detail/string_concat.hpp> | |
6656 | |
6657 | |
6658 NLOHMANN_JSON_NAMESPACE_BEGIN | |
6659 | |
6660 /*! | |
6661 @brief SAX interface | |
6662 | |
6663 This class describes the SAX interface used by @ref nlohmann::json::sax_parse. | |
6664 Each function is called in different situations while the input is parsed. The | |
6665 boolean return value informs the parser whether to continue processing the | |
6666 input. | |
6667 */ | |
6668 template<typename BasicJsonType> | |
6669 struct json_sax | |
6670 { | |
6671 using number_integer_t = typename BasicJsonType::number_integer_t; | |
6672 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
6673 using number_float_t = typename BasicJsonType::number_float_t; | |
6674 using string_t = typename BasicJsonType::string_t; | |
6675 using binary_t = typename BasicJsonType::binary_t; | |
6676 | |
6677 /*! | |
6678 @brief a null value was read | |
6679 @return whether parsing should proceed | |
6680 */ | |
6681 virtual bool null() = 0; | |
6682 | |
6683 /*! | |
6684 @brief a boolean value was read | |
6685 @param[in] val boolean value | |
6686 @return whether parsing should proceed | |
6687 */ | |
6688 virtual bool boolean(bool val) = 0; | |
6689 | |
6690 /*! | |
6691 @brief an integer number was read | |
6692 @param[in] val integer value | |
6693 @return whether parsing should proceed | |
6694 */ | |
6695 virtual bool number_integer(number_integer_t val) = 0; | |
6696 | |
6697 /*! | |
6698 @brief an unsigned integer number was read | |
6699 @param[in] val unsigned integer value | |
6700 @return whether parsing should proceed | |
6701 */ | |
6702 virtual bool number_unsigned(number_unsigned_t val) = 0; | |
6703 | |
6704 /*! | |
6705 @brief a floating-point number was read | |
6706 @param[in] val floating-point value | |
6707 @param[in] s raw token value | |
6708 @return whether parsing should proceed | |
6709 */ | |
6710 virtual bool number_float(number_float_t val, const string_t& s) = 0; | |
6711 | |
6712 /*! | |
6713 @brief a string value was read | |
6714 @param[in] val string value | |
6715 @return whether parsing should proceed | |
6716 @note It is safe to move the passed string value. | |
6717 */ | |
6718 virtual bool string(string_t& val) = 0; | |
6719 | |
6720 /*! | |
6721 @brief a binary value was read | |
6722 @param[in] val binary value | |
6723 @return whether parsing should proceed | |
6724 @note It is safe to move the passed binary value. | |
6725 */ | |
6726 virtual bool binary(binary_t& val) = 0; | |
6727 | |
6728 /*! | |
6729 @brief the beginning of an object was read | |
6730 @param[in] elements number of object elements or -1 if unknown | |
6731 @return whether parsing should proceed | |
6732 @note binary formats may report the number of elements | |
6733 */ | |
6734 virtual bool start_object(std::size_t elements) = 0; | |
6735 | |
6736 /*! | |
6737 @brief an object key was read | |
6738 @param[in] val object key | |
6739 @return whether parsing should proceed | |
6740 @note It is safe to move the passed string. | |
6741 */ | |
6742 virtual bool key(string_t& val) = 0; | |
6743 | |
6744 /*! | |
6745 @brief the end of an object was read | |
6746 @return whether parsing should proceed | |
6747 */ | |
6748 virtual bool end_object() = 0; | |
6749 | |
6750 /*! | |
6751 @brief the beginning of an array was read | |
6752 @param[in] elements number of array elements or -1 if unknown | |
6753 @return whether parsing should proceed | |
6754 @note binary formats may report the number of elements | |
6755 */ | |
6756 virtual bool start_array(std::size_t elements) = 0; | |
6757 | |
6758 /*! | |
6759 @brief the end of an array was read | |
6760 @return whether parsing should proceed | |
6761 */ | |
6762 virtual bool end_array() = 0; | |
6763 | |
6764 /*! | |
6765 @brief a parse error occurred | |
6766 @param[in] position the position in the input where the error occurs | |
6767 @param[in] last_token the last read token | |
6768 @param[in] ex an exception object describing the error | |
6769 @return whether parsing should proceed (must return false) | |
6770 */ | |
6771 virtual bool parse_error(std::size_t position, | |
6772 const std::string& last_token, | |
6773 const detail::exception& ex) = 0; | |
6774 | |
6775 json_sax() = default; | |
6776 json_sax(const json_sax&) = default; | |
6777 json_sax(json_sax&&) noexcept = default; | |
6778 json_sax& operator=(const json_sax&) = default; | |
6779 json_sax& operator=(json_sax&&) noexcept = default; | |
6780 virtual ~json_sax() = default; | |
6781 }; | |
6782 | |
6783 namespace detail | |
6784 { | |
6785 /*! | |
6786 @brief SAX implementation to create a JSON value from SAX events | |
6787 | |
6788 This class implements the @ref json_sax interface and processes the SAX events | |
6789 to create a JSON value which makes it basically a DOM parser. The structure or | |
6790 hierarchy of the JSON value is managed by the stack `ref_stack` which contains | |
6791 a pointer to the respective array or object for each recursion depth. | |
6792 | |
6793 After successful parsing, the value that is passed by reference to the | |
6794 constructor contains the parsed value. | |
6795 | |
6796 @tparam BasicJsonType the JSON type | |
6797 */ | |
6798 template<typename BasicJsonType> | |
6799 class json_sax_dom_parser | |
6800 { | |
6801 public: | |
6802 using number_integer_t = typename BasicJsonType::number_integer_t; | |
6803 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
6804 using number_float_t = typename BasicJsonType::number_float_t; | |
6805 using string_t = typename BasicJsonType::string_t; | |
6806 using binary_t = typename BasicJsonType::binary_t; | |
6807 | |
6808 /*! | |
6809 @param[in,out] r reference to a JSON value that is manipulated while | |
6810 parsing | |
6811 @param[in] allow_exceptions_ whether parse errors yield exceptions | |
6812 */ | |
6813 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) | |
6814 : root(r), allow_exceptions(allow_exceptions_) | |
6815 {} | |
6816 | |
6817 // make class move-only | |
6818 json_sax_dom_parser(const json_sax_dom_parser&) = delete; | |
6819 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
6820 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; | |
6821 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
6822 ~json_sax_dom_parser() = default; | |
6823 | |
6824 bool null() | |
6825 { | |
6826 handle_value(nullptr); | |
6827 return true; | |
6828 } | |
6829 | |
6830 bool boolean(bool val) | |
6831 { | |
6832 handle_value(val); | |
6833 return true; | |
6834 } | |
6835 | |
6836 bool number_integer(number_integer_t val) | |
6837 { | |
6838 handle_value(val); | |
6839 return true; | |
6840 } | |
6841 | |
6842 bool number_unsigned(number_unsigned_t val) | |
6843 { | |
6844 handle_value(val); | |
6845 return true; | |
6846 } | |
6847 | |
6848 bool number_float(number_float_t val, const string_t& /*unused*/) | |
6849 { | |
6850 handle_value(val); | |
6851 return true; | |
6852 } | |
6853 | |
6854 bool string(string_t& val) | |
6855 { | |
6856 handle_value(val); | |
6857 return true; | |
6858 } | |
6859 | |
6860 bool binary(binary_t& val) | |
6861 { | |
6862 handle_value(std::move(val)); | |
6863 return true; | |
6864 } | |
6865 | |
6866 bool start_object(std::size_t len) | |
6867 { | |
6868 ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); | |
6869 | |
6870 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | |
6871 { | |
6872 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); | |
6873 } | |
6874 | |
6875 return true; | |
6876 } | |
6877 | |
6878 bool key(string_t& val) | |
6879 { | |
6880 JSON_ASSERT(!ref_stack.empty()); | |
6881 JSON_ASSERT(ref_stack.back()->is_object()); | |
6882 | |
6883 // add null at given key and store the reference for later | |
6884 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); | |
6885 return true; | |
6886 } | |
6887 | |
6888 bool end_object() | |
6889 { | |
6890 JSON_ASSERT(!ref_stack.empty()); | |
6891 JSON_ASSERT(ref_stack.back()->is_object()); | |
6892 | |
6893 ref_stack.back()->set_parents(); | |
6894 ref_stack.pop_back(); | |
6895 return true; | |
6896 } | |
6897 | |
6898 bool start_array(std::size_t len) | |
6899 { | |
6900 ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); | |
6901 | |
6902 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | |
6903 { | |
6904 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); | |
6905 } | |
6906 | |
6907 return true; | |
6908 } | |
6909 | |
6910 bool end_array() | |
6911 { | |
6912 JSON_ASSERT(!ref_stack.empty()); | |
6913 JSON_ASSERT(ref_stack.back()->is_array()); | |
6914 | |
6915 ref_stack.back()->set_parents(); | |
6916 ref_stack.pop_back(); | |
6917 return true; | |
6918 } | |
6919 | |
6920 template<class Exception> | |
6921 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, | |
6922 const Exception& ex) | |
6923 { | |
6924 errored = true; | |
6925 static_cast<void>(ex); | |
6926 if (allow_exceptions) | |
6927 { | |
6928 JSON_THROW(ex); | |
6929 } | |
6930 return false; | |
6931 } | |
6932 | |
6933 constexpr bool is_errored() const | |
6934 { | |
6935 return errored; | |
6936 } | |
6937 | |
6938 private: | |
6939 /*! | |
6940 @invariant If the ref stack is empty, then the passed value will be the new | |
6941 root. | |
6942 @invariant If the ref stack contains a value, then it is an array or an | |
6943 object to which we can add elements | |
6944 */ | |
6945 template<typename Value> | |
6946 JSON_HEDLEY_RETURNS_NON_NULL | |
6947 BasicJsonType* handle_value(Value&& v) | |
6948 { | |
6949 if (ref_stack.empty()) | |
6950 { | |
6951 root = BasicJsonType(std::forward<Value>(v)); | |
6952 return &root; | |
6953 } | |
6954 | |
6955 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); | |
6956 | |
6957 if (ref_stack.back()->is_array()) | |
6958 { | |
6959 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v)); | |
6960 return &(ref_stack.back()->m_data.m_value.array->back()); | |
6961 } | |
6962 | |
6963 JSON_ASSERT(ref_stack.back()->is_object()); | |
6964 JSON_ASSERT(object_element); | |
6965 *object_element = BasicJsonType(std::forward<Value>(v)); | |
6966 return object_element; | |
6967 } | |
6968 | |
6969 /// the parsed JSON value | |
6970 BasicJsonType& root; | |
6971 /// stack to model hierarchy of values | |
6972 std::vector<BasicJsonType*> ref_stack {}; | |
6973 /// helper to hold the reference for the next object element | |
6974 BasicJsonType* object_element = nullptr; | |
6975 /// whether a syntax error occurred | |
6976 bool errored = false; | |
6977 /// whether to throw exceptions in case of errors | |
6978 const bool allow_exceptions = true; | |
6979 }; | |
6980 | |
6981 template<typename BasicJsonType> | |
6982 class json_sax_dom_callback_parser | |
6983 { | |
6984 public: | |
6985 using number_integer_t = typename BasicJsonType::number_integer_t; | |
6986 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
6987 using number_float_t = typename BasicJsonType::number_float_t; | |
6988 using string_t = typename BasicJsonType::string_t; | |
6989 using binary_t = typename BasicJsonType::binary_t; | |
6990 using parser_callback_t = typename BasicJsonType::parser_callback_t; | |
6991 using parse_event_t = typename BasicJsonType::parse_event_t; | |
6992 | |
6993 json_sax_dom_callback_parser(BasicJsonType& r, | |
6994 const parser_callback_t cb, | |
6995 const bool allow_exceptions_ = true) | |
6996 : root(r), callback(cb), allow_exceptions(allow_exceptions_) | |
6997 { | |
6998 keep_stack.push_back(true); | |
6999 } | |
7000 | |
7001 // make class move-only | |
7002 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; | |
7003 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
7004 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; | |
7005 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
7006 ~json_sax_dom_callback_parser() = default; | |
7007 | |
7008 bool null() | |
7009 { | |
7010 handle_value(nullptr); | |
7011 return true; | |
7012 } | |
7013 | |
7014 bool boolean(bool val) | |
7015 { | |
7016 handle_value(val); | |
7017 return true; | |
7018 } | |
7019 | |
7020 bool number_integer(number_integer_t val) | |
7021 { | |
7022 handle_value(val); | |
7023 return true; | |
7024 } | |
7025 | |
7026 bool number_unsigned(number_unsigned_t val) | |
7027 { | |
7028 handle_value(val); | |
7029 return true; | |
7030 } | |
7031 | |
7032 bool number_float(number_float_t val, const string_t& /*unused*/) | |
7033 { | |
7034 handle_value(val); | |
7035 return true; | |
7036 } | |
7037 | |
7038 bool string(string_t& val) | |
7039 { | |
7040 handle_value(val); | |
7041 return true; | |
7042 } | |
7043 | |
7044 bool binary(binary_t& val) | |
7045 { | |
7046 handle_value(std::move(val)); | |
7047 return true; | |
7048 } | |
7049 | |
7050 bool start_object(std::size_t len) | |
7051 { | |
7052 // check callback for object start | |
7053 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); | |
7054 keep_stack.push_back(keep); | |
7055 | |
7056 auto val = handle_value(BasicJsonType::value_t::object, true); | |
7057 ref_stack.push_back(val.second); | |
7058 | |
7059 // check object limit | |
7060 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | |
7061 { | |
7062 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); | |
7063 } | |
7064 | |
7065 return true; | |
7066 } | |
7067 | |
7068 bool key(string_t& val) | |
7069 { | |
7070 BasicJsonType k = BasicJsonType(val); | |
7071 | |
7072 // check callback for key | |
7073 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); | |
7074 key_keep_stack.push_back(keep); | |
7075 | |
7076 // add discarded value at given key and store the reference for later | |
7077 if (keep && ref_stack.back()) | |
7078 { | |
7079 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); | |
7080 } | |
7081 | |
7082 return true; | |
7083 } | |
7084 | |
7085 bool end_object() | |
7086 { | |
7087 if (ref_stack.back()) | |
7088 { | |
7089 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) | |
7090 { | |
7091 // discard object | |
7092 *ref_stack.back() = discarded; | |
7093 } | |
7094 else | |
7095 { | |
7096 ref_stack.back()->set_parents(); | |
7097 } | |
7098 } | |
7099 | |
7100 JSON_ASSERT(!ref_stack.empty()); | |
7101 JSON_ASSERT(!keep_stack.empty()); | |
7102 ref_stack.pop_back(); | |
7103 keep_stack.pop_back(); | |
7104 | |
7105 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) | |
7106 { | |
7107 // remove discarded value | |
7108 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) | |
7109 { | |
7110 if (it->is_discarded()) | |
7111 { | |
7112 ref_stack.back()->erase(it); | |
7113 break; | |
7114 } | |
7115 } | |
7116 } | |
7117 | |
7118 return true; | |
7119 } | |
7120 | |
7121 bool start_array(std::size_t len) | |
7122 { | |
7123 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); | |
7124 keep_stack.push_back(keep); | |
7125 | |
7126 auto val = handle_value(BasicJsonType::value_t::array, true); | |
7127 ref_stack.push_back(val.second); | |
7128 | |
7129 // check array limit | |
7130 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) | |
7131 { | |
7132 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); | |
7133 } | |
7134 | |
7135 return true; | |
7136 } | |
7137 | |
7138 bool end_array() | |
7139 { | |
7140 bool keep = true; | |
7141 | |
7142 if (ref_stack.back()) | |
7143 { | |
7144 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); | |
7145 if (keep) | |
7146 { | |
7147 ref_stack.back()->set_parents(); | |
7148 } | |
7149 else | |
7150 { | |
7151 // discard array | |
7152 *ref_stack.back() = discarded; | |
7153 } | |
7154 } | |
7155 | |
7156 JSON_ASSERT(!ref_stack.empty()); | |
7157 JSON_ASSERT(!keep_stack.empty()); | |
7158 ref_stack.pop_back(); | |
7159 keep_stack.pop_back(); | |
7160 | |
7161 // remove discarded value | |
7162 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) | |
7163 { | |
7164 ref_stack.back()->m_data.m_value.array->pop_back(); | |
7165 } | |
7166 | |
7167 return true; | |
7168 } | |
7169 | |
7170 template<class Exception> | |
7171 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, | |
7172 const Exception& ex) | |
7173 { | |
7174 errored = true; | |
7175 static_cast<void>(ex); | |
7176 if (allow_exceptions) | |
7177 { | |
7178 JSON_THROW(ex); | |
7179 } | |
7180 return false; | |
7181 } | |
7182 | |
7183 constexpr bool is_errored() const | |
7184 { | |
7185 return errored; | |
7186 } | |
7187 | |
7188 private: | |
7189 /*! | |
7190 @param[in] v value to add to the JSON value we build during parsing | |
7191 @param[in] skip_callback whether we should skip calling the callback | |
7192 function; this is required after start_array() and | |
7193 start_object() SAX events, because otherwise we would call the | |
7194 callback function with an empty array or object, respectively. | |
7195 | |
7196 @invariant If the ref stack is empty, then the passed value will be the new | |
7197 root. | |
7198 @invariant If the ref stack contains a value, then it is an array or an | |
7199 object to which we can add elements | |
7200 | |
7201 @return pair of boolean (whether value should be kept) and pointer (to the | |
7202 passed value in the ref_stack hierarchy; nullptr if not kept) | |
7203 */ | |
7204 template<typename Value> | |
7205 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) | |
7206 { | |
7207 JSON_ASSERT(!keep_stack.empty()); | |
7208 | |
7209 // do not handle this value if we know it would be added to a discarded | |
7210 // container | |
7211 if (!keep_stack.back()) | |
7212 { | |
7213 return {false, nullptr}; | |
7214 } | |
7215 | |
7216 // create value | |
7217 auto value = BasicJsonType(std::forward<Value>(v)); | |
7218 | |
7219 // check callback | |
7220 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); | |
7221 | |
7222 // do not handle this value if we just learnt it shall be discarded | |
7223 if (!keep) | |
7224 { | |
7225 return {false, nullptr}; | |
7226 } | |
7227 | |
7228 if (ref_stack.empty()) | |
7229 { | |
7230 root = std::move(value); | |
7231 return {true, & root}; | |
7232 } | |
7233 | |
7234 // skip this value if we already decided to skip the parent | |
7235 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) | |
7236 if (!ref_stack.back()) | |
7237 { | |
7238 return {false, nullptr}; | |
7239 } | |
7240 | |
7241 // we now only expect arrays and objects | |
7242 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); | |
7243 | |
7244 // array | |
7245 if (ref_stack.back()->is_array()) | |
7246 { | |
7247 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); | |
7248 return {true, & (ref_stack.back()->m_data.m_value.array->back())}; | |
7249 } | |
7250 | |
7251 // object | |
7252 JSON_ASSERT(ref_stack.back()->is_object()); | |
7253 // check if we should store an element for the current key | |
7254 JSON_ASSERT(!key_keep_stack.empty()); | |
7255 const bool store_element = key_keep_stack.back(); | |
7256 key_keep_stack.pop_back(); | |
7257 | |
7258 if (!store_element) | |
7259 { | |
7260 return {false, nullptr}; | |
7261 } | |
7262 | |
7263 JSON_ASSERT(object_element); | |
7264 *object_element = std::move(value); | |
7265 return {true, object_element}; | |
7266 } | |
7267 | |
7268 /// the parsed JSON value | |
7269 BasicJsonType& root; | |
7270 /// stack to model hierarchy of values | |
7271 std::vector<BasicJsonType*> ref_stack {}; | |
7272 /// stack to manage which values to keep | |
7273 std::vector<bool> keep_stack {}; | |
7274 /// stack to manage which object keys to keep | |
7275 std::vector<bool> key_keep_stack {}; | |
7276 /// helper to hold the reference for the next object element | |
7277 BasicJsonType* object_element = nullptr; | |
7278 /// whether a syntax error occurred | |
7279 bool errored = false; | |
7280 /// callback function | |
7281 const parser_callback_t callback = nullptr; | |
7282 /// whether to throw exceptions in case of errors | |
7283 const bool allow_exceptions = true; | |
7284 /// a discarded value for the callback | |
7285 BasicJsonType discarded = BasicJsonType::value_t::discarded; | |
7286 }; | |
7287 | |
7288 template<typename BasicJsonType> | |
7289 class json_sax_acceptor | |
7290 { | |
7291 public: | |
7292 using number_integer_t = typename BasicJsonType::number_integer_t; | |
7293 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
7294 using number_float_t = typename BasicJsonType::number_float_t; | |
7295 using string_t = typename BasicJsonType::string_t; | |
7296 using binary_t = typename BasicJsonType::binary_t; | |
7297 | |
7298 bool null() | |
7299 { | |
7300 return true; | |
7301 } | |
7302 | |
7303 bool boolean(bool /*unused*/) | |
7304 { | |
7305 return true; | |
7306 } | |
7307 | |
7308 bool number_integer(number_integer_t /*unused*/) | |
7309 { | |
7310 return true; | |
7311 } | |
7312 | |
7313 bool number_unsigned(number_unsigned_t /*unused*/) | |
7314 { | |
7315 return true; | |
7316 } | |
7317 | |
7318 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) | |
7319 { | |
7320 return true; | |
7321 } | |
7322 | |
7323 bool string(string_t& /*unused*/) | |
7324 { | |
7325 return true; | |
7326 } | |
7327 | |
7328 bool binary(binary_t& /*unused*/) | |
7329 { | |
7330 return true; | |
7331 } | |
7332 | |
7333 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) | |
7334 { | |
7335 return true; | |
7336 } | |
7337 | |
7338 bool key(string_t& /*unused*/) | |
7339 { | |
7340 return true; | |
7341 } | |
7342 | |
7343 bool end_object() | |
7344 { | |
7345 return true; | |
7346 } | |
7347 | |
7348 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) | |
7349 { | |
7350 return true; | |
7351 } | |
7352 | |
7353 bool end_array() | |
7354 { | |
7355 return true; | |
7356 } | |
7357 | |
7358 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) | |
7359 { | |
7360 return false; | |
7361 } | |
7362 }; | |
7363 | |
7364 } // namespace detail | |
7365 NLOHMANN_JSON_NAMESPACE_END | |
7366 | |
7367 // #include <nlohmann/detail/input/lexer.hpp> | |
7368 // __ _____ _____ _____ | |
7369 // __| | __| | | | JSON for Modern C++ | |
7370 // | | |__ | | | | | | version 3.11.3 | |
7371 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
7372 // | |
7373 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
7374 // SPDX-License-Identifier: MIT | |
7375 | |
7376 | |
7377 | |
7378 #include <array> // array | |
7379 #include <clocale> // localeconv | |
7380 #include <cstddef> // size_t | |
7381 #include <cstdio> // snprintf | |
7382 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull | |
7383 #include <initializer_list> // initializer_list | |
7384 #include <string> // char_traits, string | |
7385 #include <utility> // move | |
7386 #include <vector> // vector | |
7387 | |
7388 // #include <nlohmann/detail/input/input_adapters.hpp> | |
7389 | |
7390 // #include <nlohmann/detail/input/position_t.hpp> | |
7391 | |
7392 // #include <nlohmann/detail/macro_scope.hpp> | |
7393 | |
7394 // #include <nlohmann/detail/meta/type_traits.hpp> | |
7395 | |
7396 | |
7397 NLOHMANN_JSON_NAMESPACE_BEGIN | |
7398 namespace detail | |
7399 { | |
7400 | |
7401 /////////// | |
7402 // lexer // | |
7403 /////////// | |
7404 | |
7405 template<typename BasicJsonType> | |
7406 class lexer_base | |
7407 { | |
7408 public: | |
7409 /// token types for the parser | |
7410 enum class token_type | |
7411 { | |
7412 uninitialized, ///< indicating the scanner is uninitialized | |
7413 literal_true, ///< the `true` literal | |
7414 literal_false, ///< the `false` literal | |
7415 literal_null, ///< the `null` literal | |
7416 value_string, ///< a string -- use get_string() for actual value | |
7417 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value | |
7418 value_integer, ///< a signed integer -- use get_number_integer() for actual value | |
7419 value_float, ///< an floating point number -- use get_number_float() for actual value | |
7420 begin_array, ///< the character for array begin `[` | |
7421 begin_object, ///< the character for object begin `{` | |
7422 end_array, ///< the character for array end `]` | |
7423 end_object, ///< the character for object end `}` | |
7424 name_separator, ///< the name separator `:` | |
7425 value_separator, ///< the value separator `,` | |
7426 parse_error, ///< indicating a parse error | |
7427 end_of_input, ///< indicating the end of the input buffer | |
7428 literal_or_value ///< a literal or the begin of a value (only for diagnostics) | |
7429 }; | |
7430 | |
7431 /// return name of values of type token_type (only used for errors) | |
7432 JSON_HEDLEY_RETURNS_NON_NULL | |
7433 JSON_HEDLEY_CONST | |
7434 static const char* token_type_name(const token_type t) noexcept | |
7435 { | |
7436 switch (t) | |
7437 { | |
7438 case token_type::uninitialized: | |
7439 return "<uninitialized>"; | |
7440 case token_type::literal_true: | |
7441 return "true literal"; | |
7442 case token_type::literal_false: | |
7443 return "false literal"; | |
7444 case token_type::literal_null: | |
7445 return "null literal"; | |
7446 case token_type::value_string: | |
7447 return "string literal"; | |
7448 case token_type::value_unsigned: | |
7449 case token_type::value_integer: | |
7450 case token_type::value_float: | |
7451 return "number literal"; | |
7452 case token_type::begin_array: | |
7453 return "'['"; | |
7454 case token_type::begin_object: | |
7455 return "'{'"; | |
7456 case token_type::end_array: | |
7457 return "']'"; | |
7458 case token_type::end_object: | |
7459 return "'}'"; | |
7460 case token_type::name_separator: | |
7461 return "':'"; | |
7462 case token_type::value_separator: | |
7463 return "','"; | |
7464 case token_type::parse_error: | |
7465 return "<parse error>"; | |
7466 case token_type::end_of_input: | |
7467 return "end of input"; | |
7468 case token_type::literal_or_value: | |
7469 return "'[', '{', or a literal"; | |
7470 // LCOV_EXCL_START | |
7471 default: // catch non-enum values | |
7472 return "unknown token"; | |
7473 // LCOV_EXCL_STOP | |
7474 } | |
7475 } | |
7476 }; | |
7477 /*! | |
7478 @brief lexical analysis | |
7479 | |
7480 This class organizes the lexical analysis during JSON deserialization. | |
7481 */ | |
7482 template<typename BasicJsonType, typename InputAdapterType> | |
7483 class lexer : public lexer_base<BasicJsonType> | |
7484 { | |
7485 using number_integer_t = typename BasicJsonType::number_integer_t; | |
7486 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
7487 using number_float_t = typename BasicJsonType::number_float_t; | |
7488 using string_t = typename BasicJsonType::string_t; | |
7489 using char_type = typename InputAdapterType::char_type; | |
7490 using char_int_type = typename char_traits<char_type>::int_type; | |
7491 | |
7492 public: | |
7493 using token_type = typename lexer_base<BasicJsonType>::token_type; | |
7494 | |
7495 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept | |
7496 : ia(std::move(adapter)) | |
7497 , ignore_comments(ignore_comments_) | |
7498 , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) | |
7499 {} | |
7500 | |
7501 // delete because of pointer members | |
7502 lexer(const lexer&) = delete; | |
7503 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
7504 lexer& operator=(lexer&) = delete; | |
7505 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
7506 ~lexer() = default; | |
7507 | |
7508 private: | |
7509 ///////////////////// | |
7510 // locales | |
7511 ///////////////////// | |
7512 | |
7513 /// return the locale-dependent decimal point | |
7514 JSON_HEDLEY_PURE | |
7515 static char get_decimal_point() noexcept | |
7516 { | |
7517 const auto* loc = localeconv(); | |
7518 JSON_ASSERT(loc != nullptr); | |
7519 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); | |
7520 } | |
7521 | |
7522 ///////////////////// | |
7523 // scan functions | |
7524 ///////////////////// | |
7525 | |
7526 /*! | |
7527 @brief get codepoint from 4 hex characters following `\u` | |
7528 | |
7529 For input "\u c1 c2 c3 c4" the codepoint is: | |
7530 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 | |
7531 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) | |
7532 | |
7533 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' | |
7534 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The | |
7535 conversion is done by subtracting the offset (0x30, 0x37, and 0x57) | |
7536 between the ASCII value of the character and the desired integer value. | |
7537 | |
7538 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or | |
7539 non-hex character) | |
7540 */ | |
7541 int get_codepoint() | |
7542 { | |
7543 // this function only makes sense after reading `\u` | |
7544 JSON_ASSERT(current == 'u'); | |
7545 int codepoint = 0; | |
7546 | |
7547 const auto factors = { 12u, 8u, 4u, 0u }; | |
7548 for (const auto factor : factors) | |
7549 { | |
7550 get(); | |
7551 | |
7552 if (current >= '0' && current <= '9') | |
7553 { | |
7554 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor); | |
7555 } | |
7556 else if (current >= 'A' && current <= 'F') | |
7557 { | |
7558 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor); | |
7559 } | |
7560 else if (current >= 'a' && current <= 'f') | |
7561 { | |
7562 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor); | |
7563 } | |
7564 else | |
7565 { | |
7566 return -1; | |
7567 } | |
7568 } | |
7569 | |
7570 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); | |
7571 return codepoint; | |
7572 } | |
7573 | |
7574 /*! | |
7575 @brief check if the next byte(s) are inside a given range | |
7576 | |
7577 Adds the current byte and, for each passed range, reads a new byte and | |
7578 checks if it is inside the range. If a violation was detected, set up an | |
7579 error message and return false. Otherwise, return true. | |
7580 | |
7581 @param[in] ranges list of integers; interpreted as list of pairs of | |
7582 inclusive lower and upper bound, respectively | |
7583 | |
7584 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, | |
7585 1, 2, or 3 pairs. This precondition is enforced by an assertion. | |
7586 | |
7587 @return true if and only if no range violation was detected | |
7588 */ | |
7589 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) | |
7590 { | |
7591 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); | |
7592 add(current); | |
7593 | |
7594 for (auto range = ranges.begin(); range != ranges.end(); ++range) | |
7595 { | |
7596 get(); | |
7597 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) | |
7598 { | |
7599 add(current); | |
7600 } | |
7601 else | |
7602 { | |
7603 error_message = "invalid string: ill-formed UTF-8 byte"; | |
7604 return false; | |
7605 } | |
7606 } | |
7607 | |
7608 return true; | |
7609 } | |
7610 | |
7611 /*! | |
7612 @brief scan a string literal | |
7613 | |
7614 This function scans a string according to Sect. 7 of RFC 8259. While | |
7615 scanning, bytes are escaped and copied into buffer token_buffer. Then the | |
7616 function returns successfully, token_buffer is *not* null-terminated (as it | |
7617 may contain \0 bytes), and token_buffer.size() is the number of bytes in the | |
7618 string. | |
7619 | |
7620 @return token_type::value_string if string could be successfully scanned, | |
7621 token_type::parse_error otherwise | |
7622 | |
7623 @note In case of errors, variable error_message contains a textual | |
7624 description. | |
7625 */ | |
7626 token_type scan_string() | |
7627 { | |
7628 // reset token_buffer (ignore opening quote) | |
7629 reset(); | |
7630 | |
7631 // we entered the function by reading an open quote | |
7632 JSON_ASSERT(current == '\"'); | |
7633 | |
7634 while (true) | |
7635 { | |
7636 // get next character | |
7637 switch (get()) | |
7638 { | |
7639 // end of file while parsing string | |
7640 case char_traits<char_type>::eof(): | |
7641 { | |
7642 error_message = "invalid string: missing closing quote"; | |
7643 return token_type::parse_error; | |
7644 } | |
7645 | |
7646 // closing quote | |
7647 case '\"': | |
7648 { | |
7649 return token_type::value_string; | |
7650 } | |
7651 | |
7652 // escapes | |
7653 case '\\': | |
7654 { | |
7655 switch (get()) | |
7656 { | |
7657 // quotation mark | |
7658 case '\"': | |
7659 add('\"'); | |
7660 break; | |
7661 // reverse solidus | |
7662 case '\\': | |
7663 add('\\'); | |
7664 break; | |
7665 // solidus | |
7666 case '/': | |
7667 add('/'); | |
7668 break; | |
7669 // backspace | |
7670 case 'b': | |
7671 add('\b'); | |
7672 break; | |
7673 // form feed | |
7674 case 'f': | |
7675 add('\f'); | |
7676 break; | |
7677 // line feed | |
7678 case 'n': | |
7679 add('\n'); | |
7680 break; | |
7681 // carriage return | |
7682 case 'r': | |
7683 add('\r'); | |
7684 break; | |
7685 // tab | |
7686 case 't': | |
7687 add('\t'); | |
7688 break; | |
7689 | |
7690 // unicode escapes | |
7691 case 'u': | |
7692 { | |
7693 const int codepoint1 = get_codepoint(); | |
7694 int codepoint = codepoint1; // start with codepoint1 | |
7695 | |
7696 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) | |
7697 { | |
7698 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; | |
7699 return token_type::parse_error; | |
7700 } | |
7701 | |
7702 // check if code point is a high surrogate | |
7703 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) | |
7704 { | |
7705 // expect next \uxxxx entry | |
7706 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) | |
7707 { | |
7708 const int codepoint2 = get_codepoint(); | |
7709 | |
7710 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) | |
7711 { | |
7712 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; | |
7713 return token_type::parse_error; | |
7714 } | |
7715 | |
7716 // check if codepoint2 is a low surrogate | |
7717 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) | |
7718 { | |
7719 // overwrite codepoint | |
7720 codepoint = static_cast<int>( | |
7721 // high surrogate occupies the most significant 22 bits | |
7722 (static_cast<unsigned int>(codepoint1) << 10u) | |
7723 // low surrogate occupies the least significant 15 bits | |
7724 + static_cast<unsigned int>(codepoint2) | |
7725 // there is still the 0xD800, 0xDC00 and 0x10000 noise | |
7726 // in the result, so we have to subtract with: | |
7727 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 | |
7728 - 0x35FDC00u); | |
7729 } | |
7730 else | |
7731 { | |
7732 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; | |
7733 return token_type::parse_error; | |
7734 } | |
7735 } | |
7736 else | |
7737 { | |
7738 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; | |
7739 return token_type::parse_error; | |
7740 } | |
7741 } | |
7742 else | |
7743 { | |
7744 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) | |
7745 { | |
7746 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; | |
7747 return token_type::parse_error; | |
7748 } | |
7749 } | |
7750 | |
7751 // result of the above calculation yields a proper codepoint | |
7752 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); | |
7753 | |
7754 // translate codepoint into bytes | |
7755 if (codepoint < 0x80) | |
7756 { | |
7757 // 1-byte characters: 0xxxxxxx (ASCII) | |
7758 add(static_cast<char_int_type>(codepoint)); | |
7759 } | |
7760 else if (codepoint <= 0x7FF) | |
7761 { | |
7762 // 2-byte characters: 110xxxxx 10xxxxxx | |
7763 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u))); | |
7764 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); | |
7765 } | |
7766 else if (codepoint <= 0xFFFF) | |
7767 { | |
7768 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx | |
7769 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u))); | |
7770 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); | |
7771 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); | |
7772 } | |
7773 else | |
7774 { | |
7775 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | |
7776 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u))); | |
7777 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu))); | |
7778 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); | |
7779 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); | |
7780 } | |
7781 | |
7782 break; | |
7783 } | |
7784 | |
7785 // other characters after escape | |
7786 default: | |
7787 error_message = "invalid string: forbidden character after backslash"; | |
7788 return token_type::parse_error; | |
7789 } | |
7790 | |
7791 break; | |
7792 } | |
7793 | |
7794 // invalid control characters | |
7795 case 0x00: | |
7796 { | |
7797 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; | |
7798 return token_type::parse_error; | |
7799 } | |
7800 | |
7801 case 0x01: | |
7802 { | |
7803 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; | |
7804 return token_type::parse_error; | |
7805 } | |
7806 | |
7807 case 0x02: | |
7808 { | |
7809 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; | |
7810 return token_type::parse_error; | |
7811 } | |
7812 | |
7813 case 0x03: | |
7814 { | |
7815 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; | |
7816 return token_type::parse_error; | |
7817 } | |
7818 | |
7819 case 0x04: | |
7820 { | |
7821 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; | |
7822 return token_type::parse_error; | |
7823 } | |
7824 | |
7825 case 0x05: | |
7826 { | |
7827 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; | |
7828 return token_type::parse_error; | |
7829 } | |
7830 | |
7831 case 0x06: | |
7832 { | |
7833 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; | |
7834 return token_type::parse_error; | |
7835 } | |
7836 | |
7837 case 0x07: | |
7838 { | |
7839 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; | |
7840 return token_type::parse_error; | |
7841 } | |
7842 | |
7843 case 0x08: | |
7844 { | |
7845 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; | |
7846 return token_type::parse_error; | |
7847 } | |
7848 | |
7849 case 0x09: | |
7850 { | |
7851 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; | |
7852 return token_type::parse_error; | |
7853 } | |
7854 | |
7855 case 0x0A: | |
7856 { | |
7857 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; | |
7858 return token_type::parse_error; | |
7859 } | |
7860 | |
7861 case 0x0B: | |
7862 { | |
7863 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; | |
7864 return token_type::parse_error; | |
7865 } | |
7866 | |
7867 case 0x0C: | |
7868 { | |
7869 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; | |
7870 return token_type::parse_error; | |
7871 } | |
7872 | |
7873 case 0x0D: | |
7874 { | |
7875 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; | |
7876 return token_type::parse_error; | |
7877 } | |
7878 | |
7879 case 0x0E: | |
7880 { | |
7881 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; | |
7882 return token_type::parse_error; | |
7883 } | |
7884 | |
7885 case 0x0F: | |
7886 { | |
7887 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; | |
7888 return token_type::parse_error; | |
7889 } | |
7890 | |
7891 case 0x10: | |
7892 { | |
7893 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; | |
7894 return token_type::parse_error; | |
7895 } | |
7896 | |
7897 case 0x11: | |
7898 { | |
7899 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; | |
7900 return token_type::parse_error; | |
7901 } | |
7902 | |
7903 case 0x12: | |
7904 { | |
7905 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; | |
7906 return token_type::parse_error; | |
7907 } | |
7908 | |
7909 case 0x13: | |
7910 { | |
7911 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; | |
7912 return token_type::parse_error; | |
7913 } | |
7914 | |
7915 case 0x14: | |
7916 { | |
7917 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; | |
7918 return token_type::parse_error; | |
7919 } | |
7920 | |
7921 case 0x15: | |
7922 { | |
7923 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; | |
7924 return token_type::parse_error; | |
7925 } | |
7926 | |
7927 case 0x16: | |
7928 { | |
7929 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; | |
7930 return token_type::parse_error; | |
7931 } | |
7932 | |
7933 case 0x17: | |
7934 { | |
7935 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; | |
7936 return token_type::parse_error; | |
7937 } | |
7938 | |
7939 case 0x18: | |
7940 { | |
7941 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; | |
7942 return token_type::parse_error; | |
7943 } | |
7944 | |
7945 case 0x19: | |
7946 { | |
7947 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; | |
7948 return token_type::parse_error; | |
7949 } | |
7950 | |
7951 case 0x1A: | |
7952 { | |
7953 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; | |
7954 return token_type::parse_error; | |
7955 } | |
7956 | |
7957 case 0x1B: | |
7958 { | |
7959 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; | |
7960 return token_type::parse_error; | |
7961 } | |
7962 | |
7963 case 0x1C: | |
7964 { | |
7965 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; | |
7966 return token_type::parse_error; | |
7967 } | |
7968 | |
7969 case 0x1D: | |
7970 { | |
7971 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; | |
7972 return token_type::parse_error; | |
7973 } | |
7974 | |
7975 case 0x1E: | |
7976 { | |
7977 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; | |
7978 return token_type::parse_error; | |
7979 } | |
7980 | |
7981 case 0x1F: | |
7982 { | |
7983 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; | |
7984 return token_type::parse_error; | |
7985 } | |
7986 | |
7987 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) | |
7988 case 0x20: | |
7989 case 0x21: | |
7990 case 0x23: | |
7991 case 0x24: | |
7992 case 0x25: | |
7993 case 0x26: | |
7994 case 0x27: | |
7995 case 0x28: | |
7996 case 0x29: | |
7997 case 0x2A: | |
7998 case 0x2B: | |
7999 case 0x2C: | |
8000 case 0x2D: | |
8001 case 0x2E: | |
8002 case 0x2F: | |
8003 case 0x30: | |
8004 case 0x31: | |
8005 case 0x32: | |
8006 case 0x33: | |
8007 case 0x34: | |
8008 case 0x35: | |
8009 case 0x36: | |
8010 case 0x37: | |
8011 case 0x38: | |
8012 case 0x39: | |
8013 case 0x3A: | |
8014 case 0x3B: | |
8015 case 0x3C: | |
8016 case 0x3D: | |
8017 case 0x3E: | |
8018 case 0x3F: | |
8019 case 0x40: | |
8020 case 0x41: | |
8021 case 0x42: | |
8022 case 0x43: | |
8023 case 0x44: | |
8024 case 0x45: | |
8025 case 0x46: | |
8026 case 0x47: | |
8027 case 0x48: | |
8028 case 0x49: | |
8029 case 0x4A: | |
8030 case 0x4B: | |
8031 case 0x4C: | |
8032 case 0x4D: | |
8033 case 0x4E: | |
8034 case 0x4F: | |
8035 case 0x50: | |
8036 case 0x51: | |
8037 case 0x52: | |
8038 case 0x53: | |
8039 case 0x54: | |
8040 case 0x55: | |
8041 case 0x56: | |
8042 case 0x57: | |
8043 case 0x58: | |
8044 case 0x59: | |
8045 case 0x5A: | |
8046 case 0x5B: | |
8047 case 0x5D: | |
8048 case 0x5E: | |
8049 case 0x5F: | |
8050 case 0x60: | |
8051 case 0x61: | |
8052 case 0x62: | |
8053 case 0x63: | |
8054 case 0x64: | |
8055 case 0x65: | |
8056 case 0x66: | |
8057 case 0x67: | |
8058 case 0x68: | |
8059 case 0x69: | |
8060 case 0x6A: | |
8061 case 0x6B: | |
8062 case 0x6C: | |
8063 case 0x6D: | |
8064 case 0x6E: | |
8065 case 0x6F: | |
8066 case 0x70: | |
8067 case 0x71: | |
8068 case 0x72: | |
8069 case 0x73: | |
8070 case 0x74: | |
8071 case 0x75: | |
8072 case 0x76: | |
8073 case 0x77: | |
8074 case 0x78: | |
8075 case 0x79: | |
8076 case 0x7A: | |
8077 case 0x7B: | |
8078 case 0x7C: | |
8079 case 0x7D: | |
8080 case 0x7E: | |
8081 case 0x7F: | |
8082 { | |
8083 add(current); | |
8084 break; | |
8085 } | |
8086 | |
8087 // U+0080..U+07FF: bytes C2..DF 80..BF | |
8088 case 0xC2: | |
8089 case 0xC3: | |
8090 case 0xC4: | |
8091 case 0xC5: | |
8092 case 0xC6: | |
8093 case 0xC7: | |
8094 case 0xC8: | |
8095 case 0xC9: | |
8096 case 0xCA: | |
8097 case 0xCB: | |
8098 case 0xCC: | |
8099 case 0xCD: | |
8100 case 0xCE: | |
8101 case 0xCF: | |
8102 case 0xD0: | |
8103 case 0xD1: | |
8104 case 0xD2: | |
8105 case 0xD3: | |
8106 case 0xD4: | |
8107 case 0xD5: | |
8108 case 0xD6: | |
8109 case 0xD7: | |
8110 case 0xD8: | |
8111 case 0xD9: | |
8112 case 0xDA: | |
8113 case 0xDB: | |
8114 case 0xDC: | |
8115 case 0xDD: | |
8116 case 0xDE: | |
8117 case 0xDF: | |
8118 { | |
8119 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) | |
8120 { | |
8121 return token_type::parse_error; | |
8122 } | |
8123 break; | |
8124 } | |
8125 | |
8126 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF | |
8127 case 0xE0: | |
8128 { | |
8129 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) | |
8130 { | |
8131 return token_type::parse_error; | |
8132 } | |
8133 break; | |
8134 } | |
8135 | |
8136 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF | |
8137 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF | |
8138 case 0xE1: | |
8139 case 0xE2: | |
8140 case 0xE3: | |
8141 case 0xE4: | |
8142 case 0xE5: | |
8143 case 0xE6: | |
8144 case 0xE7: | |
8145 case 0xE8: | |
8146 case 0xE9: | |
8147 case 0xEA: | |
8148 case 0xEB: | |
8149 case 0xEC: | |
8150 case 0xEE: | |
8151 case 0xEF: | |
8152 { | |
8153 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) | |
8154 { | |
8155 return token_type::parse_error; | |
8156 } | |
8157 break; | |
8158 } | |
8159 | |
8160 // U+D000..U+D7FF: bytes ED 80..9F 80..BF | |
8161 case 0xED: | |
8162 { | |
8163 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) | |
8164 { | |
8165 return token_type::parse_error; | |
8166 } | |
8167 break; | |
8168 } | |
8169 | |
8170 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF | |
8171 case 0xF0: | |
8172 { | |
8173 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) | |
8174 { | |
8175 return token_type::parse_error; | |
8176 } | |
8177 break; | |
8178 } | |
8179 | |
8180 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF | |
8181 case 0xF1: | |
8182 case 0xF2: | |
8183 case 0xF3: | |
8184 { | |
8185 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) | |
8186 { | |
8187 return token_type::parse_error; | |
8188 } | |
8189 break; | |
8190 } | |
8191 | |
8192 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF | |
8193 case 0xF4: | |
8194 { | |
8195 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) | |
8196 { | |
8197 return token_type::parse_error; | |
8198 } | |
8199 break; | |
8200 } | |
8201 | |
8202 // remaining bytes (80..C1 and F5..FF) are ill-formed | |
8203 default: | |
8204 { | |
8205 error_message = "invalid string: ill-formed UTF-8 byte"; | |
8206 return token_type::parse_error; | |
8207 } | |
8208 } | |
8209 } | |
8210 } | |
8211 | |
8212 /*! | |
8213 * @brief scan a comment | |
8214 * @return whether comment could be scanned successfully | |
8215 */ | |
8216 bool scan_comment() | |
8217 { | |
8218 switch (get()) | |
8219 { | |
8220 // single-line comments skip input until a newline or EOF is read | |
8221 case '/': | |
8222 { | |
8223 while (true) | |
8224 { | |
8225 switch (get()) | |
8226 { | |
8227 case '\n': | |
8228 case '\r': | |
8229 case char_traits<char_type>::eof(): | |
8230 case '\0': | |
8231 return true; | |
8232 | |
8233 default: | |
8234 break; | |
8235 } | |
8236 } | |
8237 } | |
8238 | |
8239 // multi-line comments skip input until */ is read | |
8240 case '*': | |
8241 { | |
8242 while (true) | |
8243 { | |
8244 switch (get()) | |
8245 { | |
8246 case char_traits<char_type>::eof(): | |
8247 case '\0': | |
8248 { | |
8249 error_message = "invalid comment; missing closing '*/'"; | |
8250 return false; | |
8251 } | |
8252 | |
8253 case '*': | |
8254 { | |
8255 switch (get()) | |
8256 { | |
8257 case '/': | |
8258 return true; | |
8259 | |
8260 default: | |
8261 { | |
8262 unget(); | |
8263 continue; | |
8264 } | |
8265 } | |
8266 } | |
8267 | |
8268 default: | |
8269 continue; | |
8270 } | |
8271 } | |
8272 } | |
8273 | |
8274 // unexpected character after reading '/' | |
8275 default: | |
8276 { | |
8277 error_message = "invalid comment; expecting '/' or '*' after '/'"; | |
8278 return false; | |
8279 } | |
8280 } | |
8281 } | |
8282 | |
8283 JSON_HEDLEY_NON_NULL(2) | |
8284 static void strtof(float& f, const char* str, char** endptr) noexcept | |
8285 { | |
8286 f = std::strtof(str, endptr); | |
8287 } | |
8288 | |
8289 JSON_HEDLEY_NON_NULL(2) | |
8290 static void strtof(double& f, const char* str, char** endptr) noexcept | |
8291 { | |
8292 f = std::strtod(str, endptr); | |
8293 } | |
8294 | |
8295 JSON_HEDLEY_NON_NULL(2) | |
8296 static void strtof(long double& f, const char* str, char** endptr) noexcept | |
8297 { | |
8298 f = std::strtold(str, endptr); | |
8299 } | |
8300 | |
8301 /*! | |
8302 @brief scan a number literal | |
8303 | |
8304 This function scans a string according to Sect. 6 of RFC 8259. | |
8305 | |
8306 The function is realized with a deterministic finite state machine derived | |
8307 from the grammar described in RFC 8259. Starting in state "init", the | |
8308 input is read and used to determined the next state. Only state "done" | |
8309 accepts the number. State "error" is a trap state to model errors. In the | |
8310 table below, "anything" means any character but the ones listed before. | |
8311 | |
8312 state | 0 | 1-9 | e E | + | - | . | anything | |
8313 ---------|----------|----------|----------|---------|---------|----------|----------- | |
8314 init | zero | any1 | [error] | [error] | minus | [error] | [error] | |
8315 minus | zero | any1 | [error] | [error] | [error] | [error] | [error] | |
8316 zero | done | done | exponent | done | done | decimal1 | done | |
8317 any1 | any1 | any1 | exponent | done | done | decimal1 | done | |
8318 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] | |
8319 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done | |
8320 exponent | any2 | any2 | [error] | sign | sign | [error] | [error] | |
8321 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] | |
8322 any2 | any2 | any2 | done | done | done | done | done | |
8323 | |
8324 The state machine is realized with one label per state (prefixed with | |
8325 "scan_number_") and `goto` statements between them. The state machine | |
8326 contains cycles, but any cycle can be left when EOF is read. Therefore, | |
8327 the function is guaranteed to terminate. | |
8328 | |
8329 During scanning, the read bytes are stored in token_buffer. This string is | |
8330 then converted to a signed integer, an unsigned integer, or a | |
8331 floating-point number. | |
8332 | |
8333 @return token_type::value_unsigned, token_type::value_integer, or | |
8334 token_type::value_float if number could be successfully scanned, | |
8335 token_type::parse_error otherwise | |
8336 | |
8337 @note The scanner is independent of the current locale. Internally, the | |
8338 locale's decimal point is used instead of `.` to work with the | |
8339 locale-dependent converters. | |
8340 */ | |
8341 token_type scan_number() // lgtm [cpp/use-of-goto] | |
8342 { | |
8343 // reset token_buffer to store the number's bytes | |
8344 reset(); | |
8345 | |
8346 // the type of the parsed number; initially set to unsigned; will be | |
8347 // changed if minus sign, decimal point or exponent is read | |
8348 token_type number_type = token_type::value_unsigned; | |
8349 | |
8350 // state (init): we just found out we need to scan a number | |
8351 switch (current) | |
8352 { | |
8353 case '-': | |
8354 { | |
8355 add(current); | |
8356 goto scan_number_minus; | |
8357 } | |
8358 | |
8359 case '0': | |
8360 { | |
8361 add(current); | |
8362 goto scan_number_zero; | |
8363 } | |
8364 | |
8365 case '1': | |
8366 case '2': | |
8367 case '3': | |
8368 case '4': | |
8369 case '5': | |
8370 case '6': | |
8371 case '7': | |
8372 case '8': | |
8373 case '9': | |
8374 { | |
8375 add(current); | |
8376 goto scan_number_any1; | |
8377 } | |
8378 | |
8379 // all other characters are rejected outside scan_number() | |
8380 default: // LCOV_EXCL_LINE | |
8381 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
8382 } | |
8383 | |
8384 scan_number_minus: | |
8385 // state: we just parsed a leading minus sign | |
8386 number_type = token_type::value_integer; | |
8387 switch (get()) | |
8388 { | |
8389 case '0': | |
8390 { | |
8391 add(current); | |
8392 goto scan_number_zero; | |
8393 } | |
8394 | |
8395 case '1': | |
8396 case '2': | |
8397 case '3': | |
8398 case '4': | |
8399 case '5': | |
8400 case '6': | |
8401 case '7': | |
8402 case '8': | |
8403 case '9': | |
8404 { | |
8405 add(current); | |
8406 goto scan_number_any1; | |
8407 } | |
8408 | |
8409 default: | |
8410 { | |
8411 error_message = "invalid number; expected digit after '-'"; | |
8412 return token_type::parse_error; | |
8413 } | |
8414 } | |
8415 | |
8416 scan_number_zero: | |
8417 // state: we just parse a zero (maybe with a leading minus sign) | |
8418 switch (get()) | |
8419 { | |
8420 case '.': | |
8421 { | |
8422 add(decimal_point_char); | |
8423 goto scan_number_decimal1; | |
8424 } | |
8425 | |
8426 case 'e': | |
8427 case 'E': | |
8428 { | |
8429 add(current); | |
8430 goto scan_number_exponent; | |
8431 } | |
8432 | |
8433 default: | |
8434 goto scan_number_done; | |
8435 } | |
8436 | |
8437 scan_number_any1: | |
8438 // state: we just parsed a number 0-9 (maybe with a leading minus sign) | |
8439 switch (get()) | |
8440 { | |
8441 case '0': | |
8442 case '1': | |
8443 case '2': | |
8444 case '3': | |
8445 case '4': | |
8446 case '5': | |
8447 case '6': | |
8448 case '7': | |
8449 case '8': | |
8450 case '9': | |
8451 { | |
8452 add(current); | |
8453 goto scan_number_any1; | |
8454 } | |
8455 | |
8456 case '.': | |
8457 { | |
8458 add(decimal_point_char); | |
8459 goto scan_number_decimal1; | |
8460 } | |
8461 | |
8462 case 'e': | |
8463 case 'E': | |
8464 { | |
8465 add(current); | |
8466 goto scan_number_exponent; | |
8467 } | |
8468 | |
8469 default: | |
8470 goto scan_number_done; | |
8471 } | |
8472 | |
8473 scan_number_decimal1: | |
8474 // state: we just parsed a decimal point | |
8475 number_type = token_type::value_float; | |
8476 switch (get()) | |
8477 { | |
8478 case '0': | |
8479 case '1': | |
8480 case '2': | |
8481 case '3': | |
8482 case '4': | |
8483 case '5': | |
8484 case '6': | |
8485 case '7': | |
8486 case '8': | |
8487 case '9': | |
8488 { | |
8489 add(current); | |
8490 goto scan_number_decimal2; | |
8491 } | |
8492 | |
8493 default: | |
8494 { | |
8495 error_message = "invalid number; expected digit after '.'"; | |
8496 return token_type::parse_error; | |
8497 } | |
8498 } | |
8499 | |
8500 scan_number_decimal2: | |
8501 // we just parsed at least one number after a decimal point | |
8502 switch (get()) | |
8503 { | |
8504 case '0': | |
8505 case '1': | |
8506 case '2': | |
8507 case '3': | |
8508 case '4': | |
8509 case '5': | |
8510 case '6': | |
8511 case '7': | |
8512 case '8': | |
8513 case '9': | |
8514 { | |
8515 add(current); | |
8516 goto scan_number_decimal2; | |
8517 } | |
8518 | |
8519 case 'e': | |
8520 case 'E': | |
8521 { | |
8522 add(current); | |
8523 goto scan_number_exponent; | |
8524 } | |
8525 | |
8526 default: | |
8527 goto scan_number_done; | |
8528 } | |
8529 | |
8530 scan_number_exponent: | |
8531 // we just parsed an exponent | |
8532 number_type = token_type::value_float; | |
8533 switch (get()) | |
8534 { | |
8535 case '+': | |
8536 case '-': | |
8537 { | |
8538 add(current); | |
8539 goto scan_number_sign; | |
8540 } | |
8541 | |
8542 case '0': | |
8543 case '1': | |
8544 case '2': | |
8545 case '3': | |
8546 case '4': | |
8547 case '5': | |
8548 case '6': | |
8549 case '7': | |
8550 case '8': | |
8551 case '9': | |
8552 { | |
8553 add(current); | |
8554 goto scan_number_any2; | |
8555 } | |
8556 | |
8557 default: | |
8558 { | |
8559 error_message = | |
8560 "invalid number; expected '+', '-', or digit after exponent"; | |
8561 return token_type::parse_error; | |
8562 } | |
8563 } | |
8564 | |
8565 scan_number_sign: | |
8566 // we just parsed an exponent sign | |
8567 switch (get()) | |
8568 { | |
8569 case '0': | |
8570 case '1': | |
8571 case '2': | |
8572 case '3': | |
8573 case '4': | |
8574 case '5': | |
8575 case '6': | |
8576 case '7': | |
8577 case '8': | |
8578 case '9': | |
8579 { | |
8580 add(current); | |
8581 goto scan_number_any2; | |
8582 } | |
8583 | |
8584 default: | |
8585 { | |
8586 error_message = "invalid number; expected digit after exponent sign"; | |
8587 return token_type::parse_error; | |
8588 } | |
8589 } | |
8590 | |
8591 scan_number_any2: | |
8592 // we just parsed a number after the exponent or exponent sign | |
8593 switch (get()) | |
8594 { | |
8595 case '0': | |
8596 case '1': | |
8597 case '2': | |
8598 case '3': | |
8599 case '4': | |
8600 case '5': | |
8601 case '6': | |
8602 case '7': | |
8603 case '8': | |
8604 case '9': | |
8605 { | |
8606 add(current); | |
8607 goto scan_number_any2; | |
8608 } | |
8609 | |
8610 default: | |
8611 goto scan_number_done; | |
8612 } | |
8613 | |
8614 scan_number_done: | |
8615 // unget the character after the number (we only read it to know that | |
8616 // we are done scanning a number) | |
8617 unget(); | |
8618 | |
8619 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
8620 errno = 0; | |
8621 | |
8622 // try to parse integers first and fall back to floats | |
8623 if (number_type == token_type::value_unsigned) | |
8624 { | |
8625 const auto x = std::strtoull(token_buffer.data(), &endptr, 10); | |
8626 | |
8627 // we checked the number format before | |
8628 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); | |
8629 | |
8630 if (errno == 0) | |
8631 { | |
8632 value_unsigned = static_cast<number_unsigned_t>(x); | |
8633 if (value_unsigned == x) | |
8634 { | |
8635 return token_type::value_unsigned; | |
8636 } | |
8637 } | |
8638 } | |
8639 else if (number_type == token_type::value_integer) | |
8640 { | |
8641 const auto x = std::strtoll(token_buffer.data(), &endptr, 10); | |
8642 | |
8643 // we checked the number format before | |
8644 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); | |
8645 | |
8646 if (errno == 0) | |
8647 { | |
8648 value_integer = static_cast<number_integer_t>(x); | |
8649 if (value_integer == x) | |
8650 { | |
8651 return token_type::value_integer; | |
8652 } | |
8653 } | |
8654 } | |
8655 | |
8656 // this code is reached if we parse a floating-point number or if an | |
8657 // integer conversion above failed | |
8658 strtof(value_float, token_buffer.data(), &endptr); | |
8659 | |
8660 // we checked the number format before | |
8661 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); | |
8662 | |
8663 return token_type::value_float; | |
8664 } | |
8665 | |
8666 /*! | |
8667 @param[in] literal_text the literal text to expect | |
8668 @param[in] length the length of the passed literal text | |
8669 @param[in] return_type the token type to return on success | |
8670 */ | |
8671 JSON_HEDLEY_NON_NULL(2) | |
8672 token_type scan_literal(const char_type* literal_text, const std::size_t length, | |
8673 token_type return_type) | |
8674 { | |
8675 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]); | |
8676 for (std::size_t i = 1; i < length; ++i) | |
8677 { | |
8678 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i])) | |
8679 { | |
8680 error_message = "invalid literal"; | |
8681 return token_type::parse_error; | |
8682 } | |
8683 } | |
8684 return return_type; | |
8685 } | |
8686 | |
8687 ///////////////////// | |
8688 // input management | |
8689 ///////////////////// | |
8690 | |
8691 /// reset token_buffer; current character is beginning of token | |
8692 void reset() noexcept | |
8693 { | |
8694 token_buffer.clear(); | |
8695 token_string.clear(); | |
8696 token_string.push_back(char_traits<char_type>::to_char_type(current)); | |
8697 } | |
8698 | |
8699 /* | |
8700 @brief get next character from the input | |
8701 | |
8702 This function provides the interface to the used input adapter. It does | |
8703 not throw in case the input reached EOF, but returns a | |
8704 `char_traits<char>::eof()` in that case. Stores the scanned characters | |
8705 for use in error messages. | |
8706 | |
8707 @return character read from the input | |
8708 */ | |
8709 char_int_type get() | |
8710 { | |
8711 ++position.chars_read_total; | |
8712 ++position.chars_read_current_line; | |
8713 | |
8714 if (next_unget) | |
8715 { | |
8716 // just reset the next_unget variable and work with current | |
8717 next_unget = false; | |
8718 } | |
8719 else | |
8720 { | |
8721 current = ia.get_character(); | |
8722 } | |
8723 | |
8724 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) | |
8725 { | |
8726 token_string.push_back(char_traits<char_type>::to_char_type(current)); | |
8727 } | |
8728 | |
8729 if (current == '\n') | |
8730 { | |
8731 ++position.lines_read; | |
8732 position.chars_read_current_line = 0; | |
8733 } | |
8734 | |
8735 return current; | |
8736 } | |
8737 | |
8738 /*! | |
8739 @brief unget current character (read it again on next get) | |
8740 | |
8741 We implement unget by setting variable next_unget to true. The input is not | |
8742 changed - we just simulate ungetting by modifying chars_read_total, | |
8743 chars_read_current_line, and token_string. The next call to get() will | |
8744 behave as if the unget character is read again. | |
8745 */ | |
8746 void unget() | |
8747 { | |
8748 next_unget = true; | |
8749 | |
8750 --position.chars_read_total; | |
8751 | |
8752 // in case we "unget" a newline, we have to also decrement the lines_read | |
8753 if (position.chars_read_current_line == 0) | |
8754 { | |
8755 if (position.lines_read > 0) | |
8756 { | |
8757 --position.lines_read; | |
8758 } | |
8759 } | |
8760 else | |
8761 { | |
8762 --position.chars_read_current_line; | |
8763 } | |
8764 | |
8765 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) | |
8766 { | |
8767 JSON_ASSERT(!token_string.empty()); | |
8768 token_string.pop_back(); | |
8769 } | |
8770 } | |
8771 | |
8772 /// add a character to token_buffer | |
8773 void add(char_int_type c) | |
8774 { | |
8775 token_buffer.push_back(static_cast<typename string_t::value_type>(c)); | |
8776 } | |
8777 | |
8778 public: | |
8779 ///////////////////// | |
8780 // value getters | |
8781 ///////////////////// | |
8782 | |
8783 /// return integer value | |
8784 constexpr number_integer_t get_number_integer() const noexcept | |
8785 { | |
8786 return value_integer; | |
8787 } | |
8788 | |
8789 /// return unsigned integer value | |
8790 constexpr number_unsigned_t get_number_unsigned() const noexcept | |
8791 { | |
8792 return value_unsigned; | |
8793 } | |
8794 | |
8795 /// return floating-point value | |
8796 constexpr number_float_t get_number_float() const noexcept | |
8797 { | |
8798 return value_float; | |
8799 } | |
8800 | |
8801 /// return current string value (implicitly resets the token; useful only once) | |
8802 string_t& get_string() | |
8803 { | |
8804 return token_buffer; | |
8805 } | |
8806 | |
8807 ///////////////////// | |
8808 // diagnostics | |
8809 ///////////////////// | |
8810 | |
8811 /// return position of last read token | |
8812 constexpr position_t get_position() const noexcept | |
8813 { | |
8814 return position; | |
8815 } | |
8816 | |
8817 /// return the last read token (for errors only). Will never contain EOF | |
8818 /// (an arbitrary value that is not a valid char value, often -1), because | |
8819 /// 255 may legitimately occur. May contain NUL, which should be escaped. | |
8820 std::string get_token_string() const | |
8821 { | |
8822 // escape control characters | |
8823 std::string result; | |
8824 for (const auto c : token_string) | |
8825 { | |
8826 if (static_cast<unsigned char>(c) <= '\x1F') | |
8827 { | |
8828 // escape control characters | |
8829 std::array<char, 9> cs{{}}; | |
8830 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
8831 result += cs.data(); | |
8832 } | |
8833 else | |
8834 { | |
8835 // add character as is | |
8836 result.push_back(static_cast<std::string::value_type>(c)); | |
8837 } | |
8838 } | |
8839 | |
8840 return result; | |
8841 } | |
8842 | |
8843 /// return syntax error message | |
8844 JSON_HEDLEY_RETURNS_NON_NULL | |
8845 constexpr const char* get_error_message() const noexcept | |
8846 { | |
8847 return error_message; | |
8848 } | |
8849 | |
8850 ///////////////////// | |
8851 // actual scanner | |
8852 ///////////////////// | |
8853 | |
8854 /*! | |
8855 @brief skip the UTF-8 byte order mark | |
8856 @return true iff there is no BOM or the correct BOM has been skipped | |
8857 */ | |
8858 bool skip_bom() | |
8859 { | |
8860 if (get() == 0xEF) | |
8861 { | |
8862 // check if we completely parse the BOM | |
8863 return get() == 0xBB && get() == 0xBF; | |
8864 } | |
8865 | |
8866 // the first character is not the beginning of the BOM; unget it to | |
8867 // process is later | |
8868 unget(); | |
8869 return true; | |
8870 } | |
8871 | |
8872 void skip_whitespace() | |
8873 { | |
8874 do | |
8875 { | |
8876 get(); | |
8877 } | |
8878 while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); | |
8879 } | |
8880 | |
8881 token_type scan() | |
8882 { | |
8883 // initially, skip the BOM | |
8884 if (position.chars_read_total == 0 && !skip_bom()) | |
8885 { | |
8886 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; | |
8887 return token_type::parse_error; | |
8888 } | |
8889 | |
8890 // read next character and ignore whitespace | |
8891 skip_whitespace(); | |
8892 | |
8893 // ignore comments | |
8894 while (ignore_comments && current == '/') | |
8895 { | |
8896 if (!scan_comment()) | |
8897 { | |
8898 return token_type::parse_error; | |
8899 } | |
8900 | |
8901 // skip following whitespace | |
8902 skip_whitespace(); | |
8903 } | |
8904 | |
8905 switch (current) | |
8906 { | |
8907 // structural characters | |
8908 case '[': | |
8909 return token_type::begin_array; | |
8910 case ']': | |
8911 return token_type::end_array; | |
8912 case '{': | |
8913 return token_type::begin_object; | |
8914 case '}': | |
8915 return token_type::end_object; | |
8916 case ':': | |
8917 return token_type::name_separator; | |
8918 case ',': | |
8919 return token_type::value_separator; | |
8920 | |
8921 // literals | |
8922 case 't': | |
8923 { | |
8924 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}}; | |
8925 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); | |
8926 } | |
8927 case 'f': | |
8928 { | |
8929 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}}; | |
8930 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); | |
8931 } | |
8932 case 'n': | |
8933 { | |
8934 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}}; | |
8935 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); | |
8936 } | |
8937 | |
8938 // string | |
8939 case '\"': | |
8940 return scan_string(); | |
8941 | |
8942 // number | |
8943 case '-': | |
8944 case '0': | |
8945 case '1': | |
8946 case '2': | |
8947 case '3': | |
8948 case '4': | |
8949 case '5': | |
8950 case '6': | |
8951 case '7': | |
8952 case '8': | |
8953 case '9': | |
8954 return scan_number(); | |
8955 | |
8956 // end of input (the null byte is needed when parsing from | |
8957 // string literals) | |
8958 case '\0': | |
8959 case char_traits<char_type>::eof(): | |
8960 return token_type::end_of_input; | |
8961 | |
8962 // error | |
8963 default: | |
8964 error_message = "invalid literal"; | |
8965 return token_type::parse_error; | |
8966 } | |
8967 } | |
8968 | |
8969 private: | |
8970 /// input adapter | |
8971 InputAdapterType ia; | |
8972 | |
8973 /// whether comments should be ignored (true) or signaled as errors (false) | |
8974 const bool ignore_comments = false; | |
8975 | |
8976 /// the current character | |
8977 char_int_type current = char_traits<char_type>::eof(); | |
8978 | |
8979 /// whether the next get() call should just return current | |
8980 bool next_unget = false; | |
8981 | |
8982 /// the start position of the current token | |
8983 position_t position {}; | |
8984 | |
8985 /// raw input token string (for error messages) | |
8986 std::vector<char_type> token_string {}; | |
8987 | |
8988 /// buffer for variable-length tokens (numbers, strings) | |
8989 string_t token_buffer {}; | |
8990 | |
8991 /// a description of occurred lexer errors | |
8992 const char* error_message = ""; | |
8993 | |
8994 // number values | |
8995 number_integer_t value_integer = 0; | |
8996 number_unsigned_t value_unsigned = 0; | |
8997 number_float_t value_float = 0; | |
8998 | |
8999 /// the decimal point | |
9000 const char_int_type decimal_point_char = '.'; | |
9001 }; | |
9002 | |
9003 } // namespace detail | |
9004 NLOHMANN_JSON_NAMESPACE_END | |
9005 | |
9006 // #include <nlohmann/detail/macro_scope.hpp> | |
9007 | |
9008 // #include <nlohmann/detail/meta/is_sax.hpp> | |
9009 // __ _____ _____ _____ | |
9010 // __| | __| | | | JSON for Modern C++ | |
9011 // | | |__ | | | | | | version 3.11.3 | |
9012 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
9013 // | |
9014 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
9015 // SPDX-License-Identifier: MIT | |
9016 | |
9017 | |
9018 | |
9019 #include <cstdint> // size_t | |
9020 #include <utility> // declval | |
9021 #include <string> // string | |
9022 | |
9023 // #include <nlohmann/detail/abi_macros.hpp> | |
9024 | |
9025 // #include <nlohmann/detail/meta/detected.hpp> | |
9026 | |
9027 // #include <nlohmann/detail/meta/type_traits.hpp> | |
9028 | |
9029 | |
9030 NLOHMANN_JSON_NAMESPACE_BEGIN | |
9031 namespace detail | |
9032 { | |
9033 | |
9034 template<typename T> | |
9035 using null_function_t = decltype(std::declval<T&>().null()); | |
9036 | |
9037 template<typename T> | |
9038 using boolean_function_t = | |
9039 decltype(std::declval<T&>().boolean(std::declval<bool>())); | |
9040 | |
9041 template<typename T, typename Integer> | |
9042 using number_integer_function_t = | |
9043 decltype(std::declval<T&>().number_integer(std::declval<Integer>())); | |
9044 | |
9045 template<typename T, typename Unsigned> | |
9046 using number_unsigned_function_t = | |
9047 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>())); | |
9048 | |
9049 template<typename T, typename Float, typename String> | |
9050 using number_float_function_t = decltype(std::declval<T&>().number_float( | |
9051 std::declval<Float>(), std::declval<const String&>())); | |
9052 | |
9053 template<typename T, typename String> | |
9054 using string_function_t = | |
9055 decltype(std::declval<T&>().string(std::declval<String&>())); | |
9056 | |
9057 template<typename T, typename Binary> | |
9058 using binary_function_t = | |
9059 decltype(std::declval<T&>().binary(std::declval<Binary&>())); | |
9060 | |
9061 template<typename T> | |
9062 using start_object_function_t = | |
9063 decltype(std::declval<T&>().start_object(std::declval<std::size_t>())); | |
9064 | |
9065 template<typename T, typename String> | |
9066 using key_function_t = | |
9067 decltype(std::declval<T&>().key(std::declval<String&>())); | |
9068 | |
9069 template<typename T> | |
9070 using end_object_function_t = decltype(std::declval<T&>().end_object()); | |
9071 | |
9072 template<typename T> | |
9073 using start_array_function_t = | |
9074 decltype(std::declval<T&>().start_array(std::declval<std::size_t>())); | |
9075 | |
9076 template<typename T> | |
9077 using end_array_function_t = decltype(std::declval<T&>().end_array()); | |
9078 | |
9079 template<typename T, typename Exception> | |
9080 using parse_error_function_t = decltype(std::declval<T&>().parse_error( | |
9081 std::declval<std::size_t>(), std::declval<const std::string&>(), | |
9082 std::declval<const Exception&>())); | |
9083 | |
9084 template<typename SAX, typename BasicJsonType> | |
9085 struct is_sax | |
9086 { | |
9087 private: | |
9088 static_assert(is_basic_json<BasicJsonType>::value, | |
9089 "BasicJsonType must be of type basic_json<...>"); | |
9090 | |
9091 using number_integer_t = typename BasicJsonType::number_integer_t; | |
9092 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
9093 using number_float_t = typename BasicJsonType::number_float_t; | |
9094 using string_t = typename BasicJsonType::string_t; | |
9095 using binary_t = typename BasicJsonType::binary_t; | |
9096 using exception_t = typename BasicJsonType::exception; | |
9097 | |
9098 public: | |
9099 static constexpr bool value = | |
9100 is_detected_exact<bool, null_function_t, SAX>::value && | |
9101 is_detected_exact<bool, boolean_function_t, SAX>::value && | |
9102 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value && | |
9103 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value && | |
9104 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value && | |
9105 is_detected_exact<bool, string_function_t, SAX, string_t>::value && | |
9106 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value && | |
9107 is_detected_exact<bool, start_object_function_t, SAX>::value && | |
9108 is_detected_exact<bool, key_function_t, SAX, string_t>::value && | |
9109 is_detected_exact<bool, end_object_function_t, SAX>::value && | |
9110 is_detected_exact<bool, start_array_function_t, SAX>::value && | |
9111 is_detected_exact<bool, end_array_function_t, SAX>::value && | |
9112 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value; | |
9113 }; | |
9114 | |
9115 template<typename SAX, typename BasicJsonType> | |
9116 struct is_sax_static_asserts | |
9117 { | |
9118 private: | |
9119 static_assert(is_basic_json<BasicJsonType>::value, | |
9120 "BasicJsonType must be of type basic_json<...>"); | |
9121 | |
9122 using number_integer_t = typename BasicJsonType::number_integer_t; | |
9123 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
9124 using number_float_t = typename BasicJsonType::number_float_t; | |
9125 using string_t = typename BasicJsonType::string_t; | |
9126 using binary_t = typename BasicJsonType::binary_t; | |
9127 using exception_t = typename BasicJsonType::exception; | |
9128 | |
9129 public: | |
9130 static_assert(is_detected_exact<bool, null_function_t, SAX>::value, | |
9131 "Missing/invalid function: bool null()"); | |
9132 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, | |
9133 "Missing/invalid function: bool boolean(bool)"); | |
9134 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, | |
9135 "Missing/invalid function: bool boolean(bool)"); | |
9136 static_assert( | |
9137 is_detected_exact<bool, number_integer_function_t, SAX, | |
9138 number_integer_t>::value, | |
9139 "Missing/invalid function: bool number_integer(number_integer_t)"); | |
9140 static_assert( | |
9141 is_detected_exact<bool, number_unsigned_function_t, SAX, | |
9142 number_unsigned_t>::value, | |
9143 "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); | |
9144 static_assert(is_detected_exact<bool, number_float_function_t, SAX, | |
9145 number_float_t, string_t>::value, | |
9146 "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); | |
9147 static_assert( | |
9148 is_detected_exact<bool, string_function_t, SAX, string_t>::value, | |
9149 "Missing/invalid function: bool string(string_t&)"); | |
9150 static_assert( | |
9151 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, | |
9152 "Missing/invalid function: bool binary(binary_t&)"); | |
9153 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, | |
9154 "Missing/invalid function: bool start_object(std::size_t)"); | |
9155 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, | |
9156 "Missing/invalid function: bool key(string_t&)"); | |
9157 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, | |
9158 "Missing/invalid function: bool end_object()"); | |
9159 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, | |
9160 "Missing/invalid function: bool start_array(std::size_t)"); | |
9161 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, | |
9162 "Missing/invalid function: bool end_array()"); | |
9163 static_assert( | |
9164 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value, | |
9165 "Missing/invalid function: bool parse_error(std::size_t, const " | |
9166 "std::string&, const exception&)"); | |
9167 }; | |
9168 | |
9169 } // namespace detail | |
9170 NLOHMANN_JSON_NAMESPACE_END | |
9171 | |
9172 // #include <nlohmann/detail/meta/type_traits.hpp> | |
9173 | |
9174 // #include <nlohmann/detail/string_concat.hpp> | |
9175 | |
9176 // #include <nlohmann/detail/value_t.hpp> | |
9177 | |
9178 | |
9179 NLOHMANN_JSON_NAMESPACE_BEGIN | |
9180 namespace detail | |
9181 { | |
9182 | |
9183 /// how to treat CBOR tags | |
9184 enum class cbor_tag_handler_t | |
9185 { | |
9186 error, ///< throw a parse_error exception in case of a tag | |
9187 ignore, ///< ignore tags | |
9188 store ///< store tags as binary type | |
9189 }; | |
9190 | |
9191 /*! | |
9192 @brief determine system byte order | |
9193 | |
9194 @return true if and only if system's byte order is little endian | |
9195 | |
9196 @note from https://stackoverflow.com/a/1001328/266378 | |
9197 */ | |
9198 static inline bool little_endianness(int num = 1) noexcept | |
9199 { | |
9200 return *reinterpret_cast<char*>(&num) == 1; | |
9201 } | |
9202 | |
9203 /////////////////// | |
9204 // binary reader // | |
9205 /////////////////// | |
9206 | |
9207 /*! | |
9208 @brief deserialization of CBOR, MessagePack, and UBJSON values | |
9209 */ | |
9210 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>> | |
9211 class binary_reader | |
9212 { | |
9213 using number_integer_t = typename BasicJsonType::number_integer_t; | |
9214 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
9215 using number_float_t = typename BasicJsonType::number_float_t; | |
9216 using string_t = typename BasicJsonType::string_t; | |
9217 using binary_t = typename BasicJsonType::binary_t; | |
9218 using json_sax_t = SAX; | |
9219 using char_type = typename InputAdapterType::char_type; | |
9220 using char_int_type = typename char_traits<char_type>::int_type; | |
9221 | |
9222 public: | |
9223 /*! | |
9224 @brief create a binary reader | |
9225 | |
9226 @param[in] adapter input adapter to read from | |
9227 */ | |
9228 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) | |
9229 { | |
9230 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; | |
9231 } | |
9232 | |
9233 // make class move-only | |
9234 binary_reader(const binary_reader&) = delete; | |
9235 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
9236 binary_reader& operator=(const binary_reader&) = delete; | |
9237 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) | |
9238 ~binary_reader() = default; | |
9239 | |
9240 /*! | |
9241 @param[in] format the binary format to parse | |
9242 @param[in] sax_ a SAX event processor | |
9243 @param[in] strict whether to expect the input to be consumed completed | |
9244 @param[in] tag_handler how to treat CBOR tags | |
9245 | |
9246 @return whether parsing was successful | |
9247 */ | |
9248 JSON_HEDLEY_NON_NULL(3) | |
9249 bool sax_parse(const input_format_t format, | |
9250 json_sax_t* sax_, | |
9251 const bool strict = true, | |
9252 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) | |
9253 { | |
9254 sax = sax_; | |
9255 bool result = false; | |
9256 | |
9257 switch (format) | |
9258 { | |
9259 case input_format_t::bson: | |
9260 result = parse_bson_internal(); | |
9261 break; | |
9262 | |
9263 case input_format_t::cbor: | |
9264 result = parse_cbor_internal(true, tag_handler); | |
9265 break; | |
9266 | |
9267 case input_format_t::msgpack: | |
9268 result = parse_msgpack_internal(); | |
9269 break; | |
9270 | |
9271 case input_format_t::ubjson: | |
9272 case input_format_t::bjdata: | |
9273 result = parse_ubjson_internal(); | |
9274 break; | |
9275 | |
9276 case input_format_t::json: // LCOV_EXCL_LINE | |
9277 default: // LCOV_EXCL_LINE | |
9278 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
9279 } | |
9280 | |
9281 // strict mode: next byte must be EOF | |
9282 if (result && strict) | |
9283 { | |
9284 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) | |
9285 { | |
9286 get_ignore_noop(); | |
9287 } | |
9288 else | |
9289 { | |
9290 get(); | |
9291 } | |
9292 | |
9293 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof())) | |
9294 { | |
9295 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, | |
9296 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); | |
9297 } | |
9298 } | |
9299 | |
9300 return result; | |
9301 } | |
9302 | |
9303 private: | |
9304 ////////// | |
9305 // BSON // | |
9306 ////////// | |
9307 | |
9308 /*! | |
9309 @brief Reads in a BSON-object and passes it to the SAX-parser. | |
9310 @return whether a valid BSON-value was passed to the SAX parser | |
9311 */ | |
9312 bool parse_bson_internal() | |
9313 { | |
9314 std::int32_t document_size{}; | |
9315 get_number<std::int32_t, true>(input_format_t::bson, document_size); | |
9316 | |
9317 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) | |
9318 { | |
9319 return false; | |
9320 } | |
9321 | |
9322 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) | |
9323 { | |
9324 return false; | |
9325 } | |
9326 | |
9327 return sax->end_object(); | |
9328 } | |
9329 | |
9330 /*! | |
9331 @brief Parses a C-style string from the BSON input. | |
9332 @param[in,out] result A reference to the string variable where the read | |
9333 string is to be stored. | |
9334 @return `true` if the \x00-byte indicating the end of the string was | |
9335 encountered before the EOF; false` indicates an unexpected EOF. | |
9336 */ | |
9337 bool get_bson_cstr(string_t& result) | |
9338 { | |
9339 auto out = std::back_inserter(result); | |
9340 while (true) | |
9341 { | |
9342 get(); | |
9343 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) | |
9344 { | |
9345 return false; | |
9346 } | |
9347 if (current == 0x00) | |
9348 { | |
9349 return true; | |
9350 } | |
9351 *out++ = static_cast<typename string_t::value_type>(current); | |
9352 } | |
9353 } | |
9354 | |
9355 /*! | |
9356 @brief Parses a zero-terminated string of length @a len from the BSON | |
9357 input. | |
9358 @param[in] len The length (including the zero-byte at the end) of the | |
9359 string to be read. | |
9360 @param[in,out] result A reference to the string variable where the read | |
9361 string is to be stored. | |
9362 @tparam NumberType The type of the length @a len | |
9363 @pre len >= 1 | |
9364 @return `true` if the string was successfully parsed | |
9365 */ | |
9366 template<typename NumberType> | |
9367 bool get_bson_string(const NumberType len, string_t& result) | |
9368 { | |
9369 if (JSON_HEDLEY_UNLIKELY(len < 1)) | |
9370 { | |
9371 auto last_token = get_token_string(); | |
9372 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
9373 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); | |
9374 } | |
9375 | |
9376 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof(); | |
9377 } | |
9378 | |
9379 /*! | |
9380 @brief Parses a byte array input of length @a len from the BSON input. | |
9381 @param[in] len The length of the byte array to be read. | |
9382 @param[in,out] result A reference to the binary variable where the read | |
9383 array is to be stored. | |
9384 @tparam NumberType The type of the length @a len | |
9385 @pre len >= 0 | |
9386 @return `true` if the byte array was successfully parsed | |
9387 */ | |
9388 template<typename NumberType> | |
9389 bool get_bson_binary(const NumberType len, binary_t& result) | |
9390 { | |
9391 if (JSON_HEDLEY_UNLIKELY(len < 0)) | |
9392 { | |
9393 auto last_token = get_token_string(); | |
9394 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
9395 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); | |
9396 } | |
9397 | |
9398 // All BSON binary values have a subtype | |
9399 std::uint8_t subtype{}; | |
9400 get_number<std::uint8_t>(input_format_t::bson, subtype); | |
9401 result.set_subtype(subtype); | |
9402 | |
9403 return get_binary(input_format_t::bson, len, result); | |
9404 } | |
9405 | |
9406 /*! | |
9407 @brief Read a BSON document element of the given @a element_type. | |
9408 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html | |
9409 @param[in] element_type_parse_position The position in the input stream, | |
9410 where the `element_type` was read. | |
9411 @warning Not all BSON element types are supported yet. An unsupported | |
9412 @a element_type will give rise to a parse_error.114: | |
9413 Unsupported BSON record type 0x... | |
9414 @return whether a valid BSON-object/array was passed to the SAX parser | |
9415 */ | |
9416 bool parse_bson_element_internal(const char_int_type element_type, | |
9417 const std::size_t element_type_parse_position) | |
9418 { | |
9419 switch (element_type) | |
9420 { | |
9421 case 0x01: // double | |
9422 { | |
9423 double number{}; | |
9424 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
9425 } | |
9426 | |
9427 case 0x02: // string | |
9428 { | |
9429 std::int32_t len{}; | |
9430 string_t value; | |
9431 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); | |
9432 } | |
9433 | |
9434 case 0x03: // object | |
9435 { | |
9436 return parse_bson_internal(); | |
9437 } | |
9438 | |
9439 case 0x04: // array | |
9440 { | |
9441 return parse_bson_array(); | |
9442 } | |
9443 | |
9444 case 0x05: // binary | |
9445 { | |
9446 std::int32_t len{}; | |
9447 binary_t value; | |
9448 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); | |
9449 } | |
9450 | |
9451 case 0x08: // boolean | |
9452 { | |
9453 return sax->boolean(get() != 0); | |
9454 } | |
9455 | |
9456 case 0x0A: // null | |
9457 { | |
9458 return sax->null(); | |
9459 } | |
9460 | |
9461 case 0x10: // int32 | |
9462 { | |
9463 std::int32_t value{}; | |
9464 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value); | |
9465 } | |
9466 | |
9467 case 0x12: // int64 | |
9468 { | |
9469 std::int64_t value{}; | |
9470 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value); | |
9471 } | |
9472 | |
9473 default: // anything else not supported (yet) | |
9474 { | |
9475 std::array<char, 3> cr{{}}; | |
9476 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
9477 const std::string cr_str{cr.data()}; | |
9478 return sax->parse_error(element_type_parse_position, cr_str, | |
9479 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); | |
9480 } | |
9481 } | |
9482 } | |
9483 | |
9484 /*! | |
9485 @brief Read a BSON element list (as specified in the BSON-spec) | |
9486 | |
9487 The same binary layout is used for objects and arrays, hence it must be | |
9488 indicated with the argument @a is_array which one is expected | |
9489 (true --> array, false --> object). | |
9490 | |
9491 @param[in] is_array Determines if the element list being read is to be | |
9492 treated as an object (@a is_array == false), or as an | |
9493 array (@a is_array == true). | |
9494 @return whether a valid BSON-object/array was passed to the SAX parser | |
9495 */ | |
9496 bool parse_bson_element_list(const bool is_array) | |
9497 { | |
9498 string_t key; | |
9499 | |
9500 while (auto element_type = get()) | |
9501 { | |
9502 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) | |
9503 { | |
9504 return false; | |
9505 } | |
9506 | |
9507 const std::size_t element_type_parse_position = chars_read; | |
9508 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) | |
9509 { | |
9510 return false; | |
9511 } | |
9512 | |
9513 if (!is_array && !sax->key(key)) | |
9514 { | |
9515 return false; | |
9516 } | |
9517 | |
9518 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) | |
9519 { | |
9520 return false; | |
9521 } | |
9522 | |
9523 // get_bson_cstr only appends | |
9524 key.clear(); | |
9525 } | |
9526 | |
9527 return true; | |
9528 } | |
9529 | |
9530 /*! | |
9531 @brief Reads an array from the BSON input and passes it to the SAX-parser. | |
9532 @return whether a valid BSON-array was passed to the SAX parser | |
9533 */ | |
9534 bool parse_bson_array() | |
9535 { | |
9536 std::int32_t document_size{}; | |
9537 get_number<std::int32_t, true>(input_format_t::bson, document_size); | |
9538 | |
9539 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) | |
9540 { | |
9541 return false; | |
9542 } | |
9543 | |
9544 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) | |
9545 { | |
9546 return false; | |
9547 } | |
9548 | |
9549 return sax->end_array(); | |
9550 } | |
9551 | |
9552 ////////// | |
9553 // CBOR // | |
9554 ////////// | |
9555 | |
9556 /*! | |
9557 @param[in] get_char whether a new character should be retrieved from the | |
9558 input (true) or whether the last read character should | |
9559 be considered instead (false) | |
9560 @param[in] tag_handler how CBOR tags should be treated | |
9561 | |
9562 @return whether a valid CBOR value was passed to the SAX parser | |
9563 */ | |
9564 bool parse_cbor_internal(const bool get_char, | |
9565 const cbor_tag_handler_t tag_handler) | |
9566 { | |
9567 switch (get_char ? get() : current) | |
9568 { | |
9569 // EOF | |
9570 case char_traits<char_type>::eof(): | |
9571 return unexpect_eof(input_format_t::cbor, "value"); | |
9572 | |
9573 // Integer 0x00..0x17 (0..23) | |
9574 case 0x00: | |
9575 case 0x01: | |
9576 case 0x02: | |
9577 case 0x03: | |
9578 case 0x04: | |
9579 case 0x05: | |
9580 case 0x06: | |
9581 case 0x07: | |
9582 case 0x08: | |
9583 case 0x09: | |
9584 case 0x0A: | |
9585 case 0x0B: | |
9586 case 0x0C: | |
9587 case 0x0D: | |
9588 case 0x0E: | |
9589 case 0x0F: | |
9590 case 0x10: | |
9591 case 0x11: | |
9592 case 0x12: | |
9593 case 0x13: | |
9594 case 0x14: | |
9595 case 0x15: | |
9596 case 0x16: | |
9597 case 0x17: | |
9598 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); | |
9599 | |
9600 case 0x18: // Unsigned integer (one-byte uint8_t follows) | |
9601 { | |
9602 std::uint8_t number{}; | |
9603 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); | |
9604 } | |
9605 | |
9606 case 0x19: // Unsigned integer (two-byte uint16_t follows) | |
9607 { | |
9608 std::uint16_t number{}; | |
9609 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); | |
9610 } | |
9611 | |
9612 case 0x1A: // Unsigned integer (four-byte uint32_t follows) | |
9613 { | |
9614 std::uint32_t number{}; | |
9615 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); | |
9616 } | |
9617 | |
9618 case 0x1B: // Unsigned integer (eight-byte uint64_t follows) | |
9619 { | |
9620 std::uint64_t number{}; | |
9621 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); | |
9622 } | |
9623 | |
9624 // Negative integer -1-0x00..-1-0x17 (-1..-24) | |
9625 case 0x20: | |
9626 case 0x21: | |
9627 case 0x22: | |
9628 case 0x23: | |
9629 case 0x24: | |
9630 case 0x25: | |
9631 case 0x26: | |
9632 case 0x27: | |
9633 case 0x28: | |
9634 case 0x29: | |
9635 case 0x2A: | |
9636 case 0x2B: | |
9637 case 0x2C: | |
9638 case 0x2D: | |
9639 case 0x2E: | |
9640 case 0x2F: | |
9641 case 0x30: | |
9642 case 0x31: | |
9643 case 0x32: | |
9644 case 0x33: | |
9645 case 0x34: | |
9646 case 0x35: | |
9647 case 0x36: | |
9648 case 0x37: | |
9649 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current)); | |
9650 | |
9651 case 0x38: // Negative integer (one-byte uint8_t follows) | |
9652 { | |
9653 std::uint8_t number{}; | |
9654 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); | |
9655 } | |
9656 | |
9657 case 0x39: // Negative integer -1-n (two-byte uint16_t follows) | |
9658 { | |
9659 std::uint16_t number{}; | |
9660 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); | |
9661 } | |
9662 | |
9663 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) | |
9664 { | |
9665 std::uint32_t number{}; | |
9666 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); | |
9667 } | |
9668 | |
9669 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) | |
9670 { | |
9671 std::uint64_t number{}; | |
9672 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) | |
9673 - static_cast<number_integer_t>(number)); | |
9674 } | |
9675 | |
9676 // Binary data (0x00..0x17 bytes follow) | |
9677 case 0x40: | |
9678 case 0x41: | |
9679 case 0x42: | |
9680 case 0x43: | |
9681 case 0x44: | |
9682 case 0x45: | |
9683 case 0x46: | |
9684 case 0x47: | |
9685 case 0x48: | |
9686 case 0x49: | |
9687 case 0x4A: | |
9688 case 0x4B: | |
9689 case 0x4C: | |
9690 case 0x4D: | |
9691 case 0x4E: | |
9692 case 0x4F: | |
9693 case 0x50: | |
9694 case 0x51: | |
9695 case 0x52: | |
9696 case 0x53: | |
9697 case 0x54: | |
9698 case 0x55: | |
9699 case 0x56: | |
9700 case 0x57: | |
9701 case 0x58: // Binary data (one-byte uint8_t for n follows) | |
9702 case 0x59: // Binary data (two-byte uint16_t for n follow) | |
9703 case 0x5A: // Binary data (four-byte uint32_t for n follow) | |
9704 case 0x5B: // Binary data (eight-byte uint64_t for n follow) | |
9705 case 0x5F: // Binary data (indefinite length) | |
9706 { | |
9707 binary_t b; | |
9708 return get_cbor_binary(b) && sax->binary(b); | |
9709 } | |
9710 | |
9711 // UTF-8 string (0x00..0x17 bytes follow) | |
9712 case 0x60: | |
9713 case 0x61: | |
9714 case 0x62: | |
9715 case 0x63: | |
9716 case 0x64: | |
9717 case 0x65: | |
9718 case 0x66: | |
9719 case 0x67: | |
9720 case 0x68: | |
9721 case 0x69: | |
9722 case 0x6A: | |
9723 case 0x6B: | |
9724 case 0x6C: | |
9725 case 0x6D: | |
9726 case 0x6E: | |
9727 case 0x6F: | |
9728 case 0x70: | |
9729 case 0x71: | |
9730 case 0x72: | |
9731 case 0x73: | |
9732 case 0x74: | |
9733 case 0x75: | |
9734 case 0x76: | |
9735 case 0x77: | |
9736 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) | |
9737 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) | |
9738 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) | |
9739 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) | |
9740 case 0x7F: // UTF-8 string (indefinite length) | |
9741 { | |
9742 string_t s; | |
9743 return get_cbor_string(s) && sax->string(s); | |
9744 } | |
9745 | |
9746 // array (0x00..0x17 data items follow) | |
9747 case 0x80: | |
9748 case 0x81: | |
9749 case 0x82: | |
9750 case 0x83: | |
9751 case 0x84: | |
9752 case 0x85: | |
9753 case 0x86: | |
9754 case 0x87: | |
9755 case 0x88: | |
9756 case 0x89: | |
9757 case 0x8A: | |
9758 case 0x8B: | |
9759 case 0x8C: | |
9760 case 0x8D: | |
9761 case 0x8E: | |
9762 case 0x8F: | |
9763 case 0x90: | |
9764 case 0x91: | |
9765 case 0x92: | |
9766 case 0x93: | |
9767 case 0x94: | |
9768 case 0x95: | |
9769 case 0x96: | |
9770 case 0x97: | |
9771 return get_cbor_array( | |
9772 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); | |
9773 | |
9774 case 0x98: // array (one-byte uint8_t for n follows) | |
9775 { | |
9776 std::uint8_t len{}; | |
9777 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); | |
9778 } | |
9779 | |
9780 case 0x99: // array (two-byte uint16_t for n follow) | |
9781 { | |
9782 std::uint16_t len{}; | |
9783 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); | |
9784 } | |
9785 | |
9786 case 0x9A: // array (four-byte uint32_t for n follow) | |
9787 { | |
9788 std::uint32_t len{}; | |
9789 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); | |
9790 } | |
9791 | |
9792 case 0x9B: // array (eight-byte uint64_t for n follow) | |
9793 { | |
9794 std::uint64_t len{}; | |
9795 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); | |
9796 } | |
9797 | |
9798 case 0x9F: // array (indefinite length) | |
9799 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler); | |
9800 | |
9801 // map (0x00..0x17 pairs of data items follow) | |
9802 case 0xA0: | |
9803 case 0xA1: | |
9804 case 0xA2: | |
9805 case 0xA3: | |
9806 case 0xA4: | |
9807 case 0xA5: | |
9808 case 0xA6: | |
9809 case 0xA7: | |
9810 case 0xA8: | |
9811 case 0xA9: | |
9812 case 0xAA: | |
9813 case 0xAB: | |
9814 case 0xAC: | |
9815 case 0xAD: | |
9816 case 0xAE: | |
9817 case 0xAF: | |
9818 case 0xB0: | |
9819 case 0xB1: | |
9820 case 0xB2: | |
9821 case 0xB3: | |
9822 case 0xB4: | |
9823 case 0xB5: | |
9824 case 0xB6: | |
9825 case 0xB7: | |
9826 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); | |
9827 | |
9828 case 0xB8: // map (one-byte uint8_t for n follows) | |
9829 { | |
9830 std::uint8_t len{}; | |
9831 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); | |
9832 } | |
9833 | |
9834 case 0xB9: // map (two-byte uint16_t for n follow) | |
9835 { | |
9836 std::uint16_t len{}; | |
9837 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); | |
9838 } | |
9839 | |
9840 case 0xBA: // map (four-byte uint32_t for n follow) | |
9841 { | |
9842 std::uint32_t len{}; | |
9843 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); | |
9844 } | |
9845 | |
9846 case 0xBB: // map (eight-byte uint64_t for n follow) | |
9847 { | |
9848 std::uint64_t len{}; | |
9849 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); | |
9850 } | |
9851 | |
9852 case 0xBF: // map (indefinite length) | |
9853 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler); | |
9854 | |
9855 case 0xC6: // tagged item | |
9856 case 0xC7: | |
9857 case 0xC8: | |
9858 case 0xC9: | |
9859 case 0xCA: | |
9860 case 0xCB: | |
9861 case 0xCC: | |
9862 case 0xCD: | |
9863 case 0xCE: | |
9864 case 0xCF: | |
9865 case 0xD0: | |
9866 case 0xD1: | |
9867 case 0xD2: | |
9868 case 0xD3: | |
9869 case 0xD4: | |
9870 case 0xD8: // tagged item (1 bytes follow) | |
9871 case 0xD9: // tagged item (2 bytes follow) | |
9872 case 0xDA: // tagged item (4 bytes follow) | |
9873 case 0xDB: // tagged item (8 bytes follow) | |
9874 { | |
9875 switch (tag_handler) | |
9876 { | |
9877 case cbor_tag_handler_t::error: | |
9878 { | |
9879 auto last_token = get_token_string(); | |
9880 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
9881 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); | |
9882 } | |
9883 | |
9884 case cbor_tag_handler_t::ignore: | |
9885 { | |
9886 // ignore binary subtype | |
9887 switch (current) | |
9888 { | |
9889 case 0xD8: | |
9890 { | |
9891 std::uint8_t subtype_to_ignore{}; | |
9892 get_number(input_format_t::cbor, subtype_to_ignore); | |
9893 break; | |
9894 } | |
9895 case 0xD9: | |
9896 { | |
9897 std::uint16_t subtype_to_ignore{}; | |
9898 get_number(input_format_t::cbor, subtype_to_ignore); | |
9899 break; | |
9900 } | |
9901 case 0xDA: | |
9902 { | |
9903 std::uint32_t subtype_to_ignore{}; | |
9904 get_number(input_format_t::cbor, subtype_to_ignore); | |
9905 break; | |
9906 } | |
9907 case 0xDB: | |
9908 { | |
9909 std::uint64_t subtype_to_ignore{}; | |
9910 get_number(input_format_t::cbor, subtype_to_ignore); | |
9911 break; | |
9912 } | |
9913 default: | |
9914 break; | |
9915 } | |
9916 return parse_cbor_internal(true, tag_handler); | |
9917 } | |
9918 | |
9919 case cbor_tag_handler_t::store: | |
9920 { | |
9921 binary_t b; | |
9922 // use binary subtype and store in binary container | |
9923 switch (current) | |
9924 { | |
9925 case 0xD8: | |
9926 { | |
9927 std::uint8_t subtype{}; | |
9928 get_number(input_format_t::cbor, subtype); | |
9929 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); | |
9930 break; | |
9931 } | |
9932 case 0xD9: | |
9933 { | |
9934 std::uint16_t subtype{}; | |
9935 get_number(input_format_t::cbor, subtype); | |
9936 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); | |
9937 break; | |
9938 } | |
9939 case 0xDA: | |
9940 { | |
9941 std::uint32_t subtype{}; | |
9942 get_number(input_format_t::cbor, subtype); | |
9943 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); | |
9944 break; | |
9945 } | |
9946 case 0xDB: | |
9947 { | |
9948 std::uint64_t subtype{}; | |
9949 get_number(input_format_t::cbor, subtype); | |
9950 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); | |
9951 break; | |
9952 } | |
9953 default: | |
9954 return parse_cbor_internal(true, tag_handler); | |
9955 } | |
9956 get(); | |
9957 return get_cbor_binary(b) && sax->binary(b); | |
9958 } | |
9959 | |
9960 default: // LCOV_EXCL_LINE | |
9961 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
9962 return false; // LCOV_EXCL_LINE | |
9963 } | |
9964 } | |
9965 | |
9966 case 0xF4: // false | |
9967 return sax->boolean(false); | |
9968 | |
9969 case 0xF5: // true | |
9970 return sax->boolean(true); | |
9971 | |
9972 case 0xF6: // null | |
9973 return sax->null(); | |
9974 | |
9975 case 0xF9: // Half-Precision Float (two-byte IEEE 754) | |
9976 { | |
9977 const auto byte1_raw = get(); | |
9978 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) | |
9979 { | |
9980 return false; | |
9981 } | |
9982 const auto byte2_raw = get(); | |
9983 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) | |
9984 { | |
9985 return false; | |
9986 } | |
9987 | |
9988 const auto byte1 = static_cast<unsigned char>(byte1_raw); | |
9989 const auto byte2 = static_cast<unsigned char>(byte2_raw); | |
9990 | |
9991 // code from RFC 7049, Appendix D, Figure 3: | |
9992 // As half-precision floating-point numbers were only added | |
9993 // to IEEE 754 in 2008, today's programming platforms often | |
9994 // still only have limited support for them. It is very | |
9995 // easy to include at least decoding support for them even | |
9996 // without such support. An example of a small decoder for | |
9997 // half-precision floating-point numbers in the C language | |
9998 // is shown in Fig. 3. | |
9999 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2); | |
10000 const double val = [&half] | |
10001 { | |
10002 const int exp = (half >> 10u) & 0x1Fu; | |
10003 const unsigned int mant = half & 0x3FFu; | |
10004 JSON_ASSERT(0 <= exp&& exp <= 32); | |
10005 JSON_ASSERT(mant <= 1024); | |
10006 switch (exp) | |
10007 { | |
10008 case 0: | |
10009 return std::ldexp(mant, -24); | |
10010 case 31: | |
10011 return (mant == 0) | |
10012 ? std::numeric_limits<double>::infinity() | |
10013 : std::numeric_limits<double>::quiet_NaN(); | |
10014 default: | |
10015 return std::ldexp(mant + 1024, exp - 25); | |
10016 } | |
10017 }(); | |
10018 return sax->number_float((half & 0x8000u) != 0 | |
10019 ? static_cast<number_float_t>(-val) | |
10020 : static_cast<number_float_t>(val), ""); | |
10021 } | |
10022 | |
10023 case 0xFA: // Single-Precision Float (four-byte IEEE 754) | |
10024 { | |
10025 float number{}; | |
10026 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
10027 } | |
10028 | |
10029 case 0xFB: // Double-Precision Float (eight-byte IEEE 754) | |
10030 { | |
10031 double number{}; | |
10032 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
10033 } | |
10034 | |
10035 default: // anything else (0xFF is handled inside the other types) | |
10036 { | |
10037 auto last_token = get_token_string(); | |
10038 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
10039 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); | |
10040 } | |
10041 } | |
10042 } | |
10043 | |
10044 /*! | |
10045 @brief reads a CBOR string | |
10046 | |
10047 This function first reads starting bytes to determine the expected | |
10048 string length and then copies this number of bytes into a string. | |
10049 Additionally, CBOR's strings with indefinite lengths are supported. | |
10050 | |
10051 @param[out] result created string | |
10052 | |
10053 @return whether string creation completed | |
10054 */ | |
10055 bool get_cbor_string(string_t& result) | |
10056 { | |
10057 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) | |
10058 { | |
10059 return false; | |
10060 } | |
10061 | |
10062 switch (current) | |
10063 { | |
10064 // UTF-8 string (0x00..0x17 bytes follow) | |
10065 case 0x60: | |
10066 case 0x61: | |
10067 case 0x62: | |
10068 case 0x63: | |
10069 case 0x64: | |
10070 case 0x65: | |
10071 case 0x66: | |
10072 case 0x67: | |
10073 case 0x68: | |
10074 case 0x69: | |
10075 case 0x6A: | |
10076 case 0x6B: | |
10077 case 0x6C: | |
10078 case 0x6D: | |
10079 case 0x6E: | |
10080 case 0x6F: | |
10081 case 0x70: | |
10082 case 0x71: | |
10083 case 0x72: | |
10084 case 0x73: | |
10085 case 0x74: | |
10086 case 0x75: | |
10087 case 0x76: | |
10088 case 0x77: | |
10089 { | |
10090 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); | |
10091 } | |
10092 | |
10093 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) | |
10094 { | |
10095 std::uint8_t len{}; | |
10096 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); | |
10097 } | |
10098 | |
10099 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) | |
10100 { | |
10101 std::uint16_t len{}; | |
10102 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); | |
10103 } | |
10104 | |
10105 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) | |
10106 { | |
10107 std::uint32_t len{}; | |
10108 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); | |
10109 } | |
10110 | |
10111 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) | |
10112 { | |
10113 std::uint64_t len{}; | |
10114 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); | |
10115 } | |
10116 | |
10117 case 0x7F: // UTF-8 string (indefinite length) | |
10118 { | |
10119 while (get() != 0xFF) | |
10120 { | |
10121 string_t chunk; | |
10122 if (!get_cbor_string(chunk)) | |
10123 { | |
10124 return false; | |
10125 } | |
10126 result.append(chunk); | |
10127 } | |
10128 return true; | |
10129 } | |
10130 | |
10131 default: | |
10132 { | |
10133 auto last_token = get_token_string(); | |
10134 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, | |
10135 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); | |
10136 } | |
10137 } | |
10138 } | |
10139 | |
10140 /*! | |
10141 @brief reads a CBOR byte array | |
10142 | |
10143 This function first reads starting bytes to determine the expected | |
10144 byte array length and then copies this number of bytes into the byte array. | |
10145 Additionally, CBOR's byte arrays with indefinite lengths are supported. | |
10146 | |
10147 @param[out] result created byte array | |
10148 | |
10149 @return whether byte array creation completed | |
10150 */ | |
10151 bool get_cbor_binary(binary_t& result) | |
10152 { | |
10153 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) | |
10154 { | |
10155 return false; | |
10156 } | |
10157 | |
10158 switch (current) | |
10159 { | |
10160 // Binary data (0x00..0x17 bytes follow) | |
10161 case 0x40: | |
10162 case 0x41: | |
10163 case 0x42: | |
10164 case 0x43: | |
10165 case 0x44: | |
10166 case 0x45: | |
10167 case 0x46: | |
10168 case 0x47: | |
10169 case 0x48: | |
10170 case 0x49: | |
10171 case 0x4A: | |
10172 case 0x4B: | |
10173 case 0x4C: | |
10174 case 0x4D: | |
10175 case 0x4E: | |
10176 case 0x4F: | |
10177 case 0x50: | |
10178 case 0x51: | |
10179 case 0x52: | |
10180 case 0x53: | |
10181 case 0x54: | |
10182 case 0x55: | |
10183 case 0x56: | |
10184 case 0x57: | |
10185 { | |
10186 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); | |
10187 } | |
10188 | |
10189 case 0x58: // Binary data (one-byte uint8_t for n follows) | |
10190 { | |
10191 std::uint8_t len{}; | |
10192 return get_number(input_format_t::cbor, len) && | |
10193 get_binary(input_format_t::cbor, len, result); | |
10194 } | |
10195 | |
10196 case 0x59: // Binary data (two-byte uint16_t for n follow) | |
10197 { | |
10198 std::uint16_t len{}; | |
10199 return get_number(input_format_t::cbor, len) && | |
10200 get_binary(input_format_t::cbor, len, result); | |
10201 } | |
10202 | |
10203 case 0x5A: // Binary data (four-byte uint32_t for n follow) | |
10204 { | |
10205 std::uint32_t len{}; | |
10206 return get_number(input_format_t::cbor, len) && | |
10207 get_binary(input_format_t::cbor, len, result); | |
10208 } | |
10209 | |
10210 case 0x5B: // Binary data (eight-byte uint64_t for n follow) | |
10211 { | |
10212 std::uint64_t len{}; | |
10213 return get_number(input_format_t::cbor, len) && | |
10214 get_binary(input_format_t::cbor, len, result); | |
10215 } | |
10216 | |
10217 case 0x5F: // Binary data (indefinite length) | |
10218 { | |
10219 while (get() != 0xFF) | |
10220 { | |
10221 binary_t chunk; | |
10222 if (!get_cbor_binary(chunk)) | |
10223 { | |
10224 return false; | |
10225 } | |
10226 result.insert(result.end(), chunk.begin(), chunk.end()); | |
10227 } | |
10228 return true; | |
10229 } | |
10230 | |
10231 default: | |
10232 { | |
10233 auto last_token = get_token_string(); | |
10234 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, | |
10235 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); | |
10236 } | |
10237 } | |
10238 } | |
10239 | |
10240 /*! | |
10241 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an | |
10242 array of indefinite size | |
10243 @param[in] tag_handler how CBOR tags should be treated | |
10244 @return whether array creation completed | |
10245 */ | |
10246 bool get_cbor_array(const std::size_t len, | |
10247 const cbor_tag_handler_t tag_handler) | |
10248 { | |
10249 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) | |
10250 { | |
10251 return false; | |
10252 } | |
10253 | |
10254 if (len != static_cast<std::size_t>(-1)) | |
10255 { | |
10256 for (std::size_t i = 0; i < len; ++i) | |
10257 { | |
10258 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) | |
10259 { | |
10260 return false; | |
10261 } | |
10262 } | |
10263 } | |
10264 else | |
10265 { | |
10266 while (get() != 0xFF) | |
10267 { | |
10268 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) | |
10269 { | |
10270 return false; | |
10271 } | |
10272 } | |
10273 } | |
10274 | |
10275 return sax->end_array(); | |
10276 } | |
10277 | |
10278 /*! | |
10279 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an | |
10280 object of indefinite size | |
10281 @param[in] tag_handler how CBOR tags should be treated | |
10282 @return whether object creation completed | |
10283 */ | |
10284 bool get_cbor_object(const std::size_t len, | |
10285 const cbor_tag_handler_t tag_handler) | |
10286 { | |
10287 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) | |
10288 { | |
10289 return false; | |
10290 } | |
10291 | |
10292 if (len != 0) | |
10293 { | |
10294 string_t key; | |
10295 if (len != static_cast<std::size_t>(-1)) | |
10296 { | |
10297 for (std::size_t i = 0; i < len; ++i) | |
10298 { | |
10299 get(); | |
10300 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) | |
10301 { | |
10302 return false; | |
10303 } | |
10304 | |
10305 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) | |
10306 { | |
10307 return false; | |
10308 } | |
10309 key.clear(); | |
10310 } | |
10311 } | |
10312 else | |
10313 { | |
10314 while (get() != 0xFF) | |
10315 { | |
10316 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) | |
10317 { | |
10318 return false; | |
10319 } | |
10320 | |
10321 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) | |
10322 { | |
10323 return false; | |
10324 } | |
10325 key.clear(); | |
10326 } | |
10327 } | |
10328 } | |
10329 | |
10330 return sax->end_object(); | |
10331 } | |
10332 | |
10333 ///////////// | |
10334 // MsgPack // | |
10335 ///////////// | |
10336 | |
10337 /*! | |
10338 @return whether a valid MessagePack value was passed to the SAX parser | |
10339 */ | |
10340 bool parse_msgpack_internal() | |
10341 { | |
10342 switch (get()) | |
10343 { | |
10344 // EOF | |
10345 case char_traits<char_type>::eof(): | |
10346 return unexpect_eof(input_format_t::msgpack, "value"); | |
10347 | |
10348 // positive fixint | |
10349 case 0x00: | |
10350 case 0x01: | |
10351 case 0x02: | |
10352 case 0x03: | |
10353 case 0x04: | |
10354 case 0x05: | |
10355 case 0x06: | |
10356 case 0x07: | |
10357 case 0x08: | |
10358 case 0x09: | |
10359 case 0x0A: | |
10360 case 0x0B: | |
10361 case 0x0C: | |
10362 case 0x0D: | |
10363 case 0x0E: | |
10364 case 0x0F: | |
10365 case 0x10: | |
10366 case 0x11: | |
10367 case 0x12: | |
10368 case 0x13: | |
10369 case 0x14: | |
10370 case 0x15: | |
10371 case 0x16: | |
10372 case 0x17: | |
10373 case 0x18: | |
10374 case 0x19: | |
10375 case 0x1A: | |
10376 case 0x1B: | |
10377 case 0x1C: | |
10378 case 0x1D: | |
10379 case 0x1E: | |
10380 case 0x1F: | |
10381 case 0x20: | |
10382 case 0x21: | |
10383 case 0x22: | |
10384 case 0x23: | |
10385 case 0x24: | |
10386 case 0x25: | |
10387 case 0x26: | |
10388 case 0x27: | |
10389 case 0x28: | |
10390 case 0x29: | |
10391 case 0x2A: | |
10392 case 0x2B: | |
10393 case 0x2C: | |
10394 case 0x2D: | |
10395 case 0x2E: | |
10396 case 0x2F: | |
10397 case 0x30: | |
10398 case 0x31: | |
10399 case 0x32: | |
10400 case 0x33: | |
10401 case 0x34: | |
10402 case 0x35: | |
10403 case 0x36: | |
10404 case 0x37: | |
10405 case 0x38: | |
10406 case 0x39: | |
10407 case 0x3A: | |
10408 case 0x3B: | |
10409 case 0x3C: | |
10410 case 0x3D: | |
10411 case 0x3E: | |
10412 case 0x3F: | |
10413 case 0x40: | |
10414 case 0x41: | |
10415 case 0x42: | |
10416 case 0x43: | |
10417 case 0x44: | |
10418 case 0x45: | |
10419 case 0x46: | |
10420 case 0x47: | |
10421 case 0x48: | |
10422 case 0x49: | |
10423 case 0x4A: | |
10424 case 0x4B: | |
10425 case 0x4C: | |
10426 case 0x4D: | |
10427 case 0x4E: | |
10428 case 0x4F: | |
10429 case 0x50: | |
10430 case 0x51: | |
10431 case 0x52: | |
10432 case 0x53: | |
10433 case 0x54: | |
10434 case 0x55: | |
10435 case 0x56: | |
10436 case 0x57: | |
10437 case 0x58: | |
10438 case 0x59: | |
10439 case 0x5A: | |
10440 case 0x5B: | |
10441 case 0x5C: | |
10442 case 0x5D: | |
10443 case 0x5E: | |
10444 case 0x5F: | |
10445 case 0x60: | |
10446 case 0x61: | |
10447 case 0x62: | |
10448 case 0x63: | |
10449 case 0x64: | |
10450 case 0x65: | |
10451 case 0x66: | |
10452 case 0x67: | |
10453 case 0x68: | |
10454 case 0x69: | |
10455 case 0x6A: | |
10456 case 0x6B: | |
10457 case 0x6C: | |
10458 case 0x6D: | |
10459 case 0x6E: | |
10460 case 0x6F: | |
10461 case 0x70: | |
10462 case 0x71: | |
10463 case 0x72: | |
10464 case 0x73: | |
10465 case 0x74: | |
10466 case 0x75: | |
10467 case 0x76: | |
10468 case 0x77: | |
10469 case 0x78: | |
10470 case 0x79: | |
10471 case 0x7A: | |
10472 case 0x7B: | |
10473 case 0x7C: | |
10474 case 0x7D: | |
10475 case 0x7E: | |
10476 case 0x7F: | |
10477 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); | |
10478 | |
10479 // fixmap | |
10480 case 0x80: | |
10481 case 0x81: | |
10482 case 0x82: | |
10483 case 0x83: | |
10484 case 0x84: | |
10485 case 0x85: | |
10486 case 0x86: | |
10487 case 0x87: | |
10488 case 0x88: | |
10489 case 0x89: | |
10490 case 0x8A: | |
10491 case 0x8B: | |
10492 case 0x8C: | |
10493 case 0x8D: | |
10494 case 0x8E: | |
10495 case 0x8F: | |
10496 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); | |
10497 | |
10498 // fixarray | |
10499 case 0x90: | |
10500 case 0x91: | |
10501 case 0x92: | |
10502 case 0x93: | |
10503 case 0x94: | |
10504 case 0x95: | |
10505 case 0x96: | |
10506 case 0x97: | |
10507 case 0x98: | |
10508 case 0x99: | |
10509 case 0x9A: | |
10510 case 0x9B: | |
10511 case 0x9C: | |
10512 case 0x9D: | |
10513 case 0x9E: | |
10514 case 0x9F: | |
10515 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); | |
10516 | |
10517 // fixstr | |
10518 case 0xA0: | |
10519 case 0xA1: | |
10520 case 0xA2: | |
10521 case 0xA3: | |
10522 case 0xA4: | |
10523 case 0xA5: | |
10524 case 0xA6: | |
10525 case 0xA7: | |
10526 case 0xA8: | |
10527 case 0xA9: | |
10528 case 0xAA: | |
10529 case 0xAB: | |
10530 case 0xAC: | |
10531 case 0xAD: | |
10532 case 0xAE: | |
10533 case 0xAF: | |
10534 case 0xB0: | |
10535 case 0xB1: | |
10536 case 0xB2: | |
10537 case 0xB3: | |
10538 case 0xB4: | |
10539 case 0xB5: | |
10540 case 0xB6: | |
10541 case 0xB7: | |
10542 case 0xB8: | |
10543 case 0xB9: | |
10544 case 0xBA: | |
10545 case 0xBB: | |
10546 case 0xBC: | |
10547 case 0xBD: | |
10548 case 0xBE: | |
10549 case 0xBF: | |
10550 case 0xD9: // str 8 | |
10551 case 0xDA: // str 16 | |
10552 case 0xDB: // str 32 | |
10553 { | |
10554 string_t s; | |
10555 return get_msgpack_string(s) && sax->string(s); | |
10556 } | |
10557 | |
10558 case 0xC0: // nil | |
10559 return sax->null(); | |
10560 | |
10561 case 0xC2: // false | |
10562 return sax->boolean(false); | |
10563 | |
10564 case 0xC3: // true | |
10565 return sax->boolean(true); | |
10566 | |
10567 case 0xC4: // bin 8 | |
10568 case 0xC5: // bin 16 | |
10569 case 0xC6: // bin 32 | |
10570 case 0xC7: // ext 8 | |
10571 case 0xC8: // ext 16 | |
10572 case 0xC9: // ext 32 | |
10573 case 0xD4: // fixext 1 | |
10574 case 0xD5: // fixext 2 | |
10575 case 0xD6: // fixext 4 | |
10576 case 0xD7: // fixext 8 | |
10577 case 0xD8: // fixext 16 | |
10578 { | |
10579 binary_t b; | |
10580 return get_msgpack_binary(b) && sax->binary(b); | |
10581 } | |
10582 | |
10583 case 0xCA: // float 32 | |
10584 { | |
10585 float number{}; | |
10586 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
10587 } | |
10588 | |
10589 case 0xCB: // float 64 | |
10590 { | |
10591 double number{}; | |
10592 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
10593 } | |
10594 | |
10595 case 0xCC: // uint 8 | |
10596 { | |
10597 std::uint8_t number{}; | |
10598 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); | |
10599 } | |
10600 | |
10601 case 0xCD: // uint 16 | |
10602 { | |
10603 std::uint16_t number{}; | |
10604 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); | |
10605 } | |
10606 | |
10607 case 0xCE: // uint 32 | |
10608 { | |
10609 std::uint32_t number{}; | |
10610 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); | |
10611 } | |
10612 | |
10613 case 0xCF: // uint 64 | |
10614 { | |
10615 std::uint64_t number{}; | |
10616 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); | |
10617 } | |
10618 | |
10619 case 0xD0: // int 8 | |
10620 { | |
10621 std::int8_t number{}; | |
10622 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); | |
10623 } | |
10624 | |
10625 case 0xD1: // int 16 | |
10626 { | |
10627 std::int16_t number{}; | |
10628 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); | |
10629 } | |
10630 | |
10631 case 0xD2: // int 32 | |
10632 { | |
10633 std::int32_t number{}; | |
10634 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); | |
10635 } | |
10636 | |
10637 case 0xD3: // int 64 | |
10638 { | |
10639 std::int64_t number{}; | |
10640 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); | |
10641 } | |
10642 | |
10643 case 0xDC: // array 16 | |
10644 { | |
10645 std::uint16_t len{}; | |
10646 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len)); | |
10647 } | |
10648 | |
10649 case 0xDD: // array 32 | |
10650 { | |
10651 std::uint32_t len{}; | |
10652 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len)); | |
10653 } | |
10654 | |
10655 case 0xDE: // map 16 | |
10656 { | |
10657 std::uint16_t len{}; | |
10658 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len)); | |
10659 } | |
10660 | |
10661 case 0xDF: // map 32 | |
10662 { | |
10663 std::uint32_t len{}; | |
10664 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len)); | |
10665 } | |
10666 | |
10667 // negative fixint | |
10668 case 0xE0: | |
10669 case 0xE1: | |
10670 case 0xE2: | |
10671 case 0xE3: | |
10672 case 0xE4: | |
10673 case 0xE5: | |
10674 case 0xE6: | |
10675 case 0xE7: | |
10676 case 0xE8: | |
10677 case 0xE9: | |
10678 case 0xEA: | |
10679 case 0xEB: | |
10680 case 0xEC: | |
10681 case 0xED: | |
10682 case 0xEE: | |
10683 case 0xEF: | |
10684 case 0xF0: | |
10685 case 0xF1: | |
10686 case 0xF2: | |
10687 case 0xF3: | |
10688 case 0xF4: | |
10689 case 0xF5: | |
10690 case 0xF6: | |
10691 case 0xF7: | |
10692 case 0xF8: | |
10693 case 0xF9: | |
10694 case 0xFA: | |
10695 case 0xFB: | |
10696 case 0xFC: | |
10697 case 0xFD: | |
10698 case 0xFE: | |
10699 case 0xFF: | |
10700 return sax->number_integer(static_cast<std::int8_t>(current)); | |
10701 | |
10702 default: // anything else | |
10703 { | |
10704 auto last_token = get_token_string(); | |
10705 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
10706 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); | |
10707 } | |
10708 } | |
10709 } | |
10710 | |
10711 /*! | |
10712 @brief reads a MessagePack string | |
10713 | |
10714 This function first reads starting bytes to determine the expected | |
10715 string length and then copies this number of bytes into a string. | |
10716 | |
10717 @param[out] result created string | |
10718 | |
10719 @return whether string creation completed | |
10720 */ | |
10721 bool get_msgpack_string(string_t& result) | |
10722 { | |
10723 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) | |
10724 { | |
10725 return false; | |
10726 } | |
10727 | |
10728 switch (current) | |
10729 { | |
10730 // fixstr | |
10731 case 0xA0: | |
10732 case 0xA1: | |
10733 case 0xA2: | |
10734 case 0xA3: | |
10735 case 0xA4: | |
10736 case 0xA5: | |
10737 case 0xA6: | |
10738 case 0xA7: | |
10739 case 0xA8: | |
10740 case 0xA9: | |
10741 case 0xAA: | |
10742 case 0xAB: | |
10743 case 0xAC: | |
10744 case 0xAD: | |
10745 case 0xAE: | |
10746 case 0xAF: | |
10747 case 0xB0: | |
10748 case 0xB1: | |
10749 case 0xB2: | |
10750 case 0xB3: | |
10751 case 0xB4: | |
10752 case 0xB5: | |
10753 case 0xB6: | |
10754 case 0xB7: | |
10755 case 0xB8: | |
10756 case 0xB9: | |
10757 case 0xBA: | |
10758 case 0xBB: | |
10759 case 0xBC: | |
10760 case 0xBD: | |
10761 case 0xBE: | |
10762 case 0xBF: | |
10763 { | |
10764 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result); | |
10765 } | |
10766 | |
10767 case 0xD9: // str 8 | |
10768 { | |
10769 std::uint8_t len{}; | |
10770 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); | |
10771 } | |
10772 | |
10773 case 0xDA: // str 16 | |
10774 { | |
10775 std::uint16_t len{}; | |
10776 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); | |
10777 } | |
10778 | |
10779 case 0xDB: // str 32 | |
10780 { | |
10781 std::uint32_t len{}; | |
10782 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); | |
10783 } | |
10784 | |
10785 default: | |
10786 { | |
10787 auto last_token = get_token_string(); | |
10788 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, | |
10789 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); | |
10790 } | |
10791 } | |
10792 } | |
10793 | |
10794 /*! | |
10795 @brief reads a MessagePack byte array | |
10796 | |
10797 This function first reads starting bytes to determine the expected | |
10798 byte array length and then copies this number of bytes into a byte array. | |
10799 | |
10800 @param[out] result created byte array | |
10801 | |
10802 @return whether byte array creation completed | |
10803 */ | |
10804 bool get_msgpack_binary(binary_t& result) | |
10805 { | |
10806 // helper function to set the subtype | |
10807 auto assign_and_return_true = [&result](std::int8_t subtype) | |
10808 { | |
10809 result.set_subtype(static_cast<std::uint8_t>(subtype)); | |
10810 return true; | |
10811 }; | |
10812 | |
10813 switch (current) | |
10814 { | |
10815 case 0xC4: // bin 8 | |
10816 { | |
10817 std::uint8_t len{}; | |
10818 return get_number(input_format_t::msgpack, len) && | |
10819 get_binary(input_format_t::msgpack, len, result); | |
10820 } | |
10821 | |
10822 case 0xC5: // bin 16 | |
10823 { | |
10824 std::uint16_t len{}; | |
10825 return get_number(input_format_t::msgpack, len) && | |
10826 get_binary(input_format_t::msgpack, len, result); | |
10827 } | |
10828 | |
10829 case 0xC6: // bin 32 | |
10830 { | |
10831 std::uint32_t len{}; | |
10832 return get_number(input_format_t::msgpack, len) && | |
10833 get_binary(input_format_t::msgpack, len, result); | |
10834 } | |
10835 | |
10836 case 0xC7: // ext 8 | |
10837 { | |
10838 std::uint8_t len{}; | |
10839 std::int8_t subtype{}; | |
10840 return get_number(input_format_t::msgpack, len) && | |
10841 get_number(input_format_t::msgpack, subtype) && | |
10842 get_binary(input_format_t::msgpack, len, result) && | |
10843 assign_and_return_true(subtype); | |
10844 } | |
10845 | |
10846 case 0xC8: // ext 16 | |
10847 { | |
10848 std::uint16_t len{}; | |
10849 std::int8_t subtype{}; | |
10850 return get_number(input_format_t::msgpack, len) && | |
10851 get_number(input_format_t::msgpack, subtype) && | |
10852 get_binary(input_format_t::msgpack, len, result) && | |
10853 assign_and_return_true(subtype); | |
10854 } | |
10855 | |
10856 case 0xC9: // ext 32 | |
10857 { | |
10858 std::uint32_t len{}; | |
10859 std::int8_t subtype{}; | |
10860 return get_number(input_format_t::msgpack, len) && | |
10861 get_number(input_format_t::msgpack, subtype) && | |
10862 get_binary(input_format_t::msgpack, len, result) && | |
10863 assign_and_return_true(subtype); | |
10864 } | |
10865 | |
10866 case 0xD4: // fixext 1 | |
10867 { | |
10868 std::int8_t subtype{}; | |
10869 return get_number(input_format_t::msgpack, subtype) && | |
10870 get_binary(input_format_t::msgpack, 1, result) && | |
10871 assign_and_return_true(subtype); | |
10872 } | |
10873 | |
10874 case 0xD5: // fixext 2 | |
10875 { | |
10876 std::int8_t subtype{}; | |
10877 return get_number(input_format_t::msgpack, subtype) && | |
10878 get_binary(input_format_t::msgpack, 2, result) && | |
10879 assign_and_return_true(subtype); | |
10880 } | |
10881 | |
10882 case 0xD6: // fixext 4 | |
10883 { | |
10884 std::int8_t subtype{}; | |
10885 return get_number(input_format_t::msgpack, subtype) && | |
10886 get_binary(input_format_t::msgpack, 4, result) && | |
10887 assign_and_return_true(subtype); | |
10888 } | |
10889 | |
10890 case 0xD7: // fixext 8 | |
10891 { | |
10892 std::int8_t subtype{}; | |
10893 return get_number(input_format_t::msgpack, subtype) && | |
10894 get_binary(input_format_t::msgpack, 8, result) && | |
10895 assign_and_return_true(subtype); | |
10896 } | |
10897 | |
10898 case 0xD8: // fixext 16 | |
10899 { | |
10900 std::int8_t subtype{}; | |
10901 return get_number(input_format_t::msgpack, subtype) && | |
10902 get_binary(input_format_t::msgpack, 16, result) && | |
10903 assign_and_return_true(subtype); | |
10904 } | |
10905 | |
10906 default: // LCOV_EXCL_LINE | |
10907 return false; // LCOV_EXCL_LINE | |
10908 } | |
10909 } | |
10910 | |
10911 /*! | |
10912 @param[in] len the length of the array | |
10913 @return whether array creation completed | |
10914 */ | |
10915 bool get_msgpack_array(const std::size_t len) | |
10916 { | |
10917 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) | |
10918 { | |
10919 return false; | |
10920 } | |
10921 | |
10922 for (std::size_t i = 0; i < len; ++i) | |
10923 { | |
10924 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) | |
10925 { | |
10926 return false; | |
10927 } | |
10928 } | |
10929 | |
10930 return sax->end_array(); | |
10931 } | |
10932 | |
10933 /*! | |
10934 @param[in] len the length of the object | |
10935 @return whether object creation completed | |
10936 */ | |
10937 bool get_msgpack_object(const std::size_t len) | |
10938 { | |
10939 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) | |
10940 { | |
10941 return false; | |
10942 } | |
10943 | |
10944 string_t key; | |
10945 for (std::size_t i = 0; i < len; ++i) | |
10946 { | |
10947 get(); | |
10948 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) | |
10949 { | |
10950 return false; | |
10951 } | |
10952 | |
10953 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) | |
10954 { | |
10955 return false; | |
10956 } | |
10957 key.clear(); | |
10958 } | |
10959 | |
10960 return sax->end_object(); | |
10961 } | |
10962 | |
10963 //////////// | |
10964 // UBJSON // | |
10965 //////////// | |
10966 | |
10967 /*! | |
10968 @param[in] get_char whether a new character should be retrieved from the | |
10969 input (true, default) or whether the last read | |
10970 character should be considered instead | |
10971 | |
10972 @return whether a valid UBJSON value was passed to the SAX parser | |
10973 */ | |
10974 bool parse_ubjson_internal(const bool get_char = true) | |
10975 { | |
10976 return get_ubjson_value(get_char ? get_ignore_noop() : current); | |
10977 } | |
10978 | |
10979 /*! | |
10980 @brief reads a UBJSON string | |
10981 | |
10982 This function is either called after reading the 'S' byte explicitly | |
10983 indicating a string, or in case of an object key where the 'S' byte can be | |
10984 left out. | |
10985 | |
10986 @param[out] result created string | |
10987 @param[in] get_char whether a new character should be retrieved from the | |
10988 input (true, default) or whether the last read | |
10989 character should be considered instead | |
10990 | |
10991 @return whether string creation completed | |
10992 */ | |
10993 bool get_ubjson_string(string_t& result, const bool get_char = true) | |
10994 { | |
10995 if (get_char) | |
10996 { | |
10997 get(); // TODO(niels): may we ignore N here? | |
10998 } | |
10999 | |
11000 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) | |
11001 { | |
11002 return false; | |
11003 } | |
11004 | |
11005 switch (current) | |
11006 { | |
11007 case 'U': | |
11008 { | |
11009 std::uint8_t len{}; | |
11010 return get_number(input_format, len) && get_string(input_format, len, result); | |
11011 } | |
11012 | |
11013 case 'i': | |
11014 { | |
11015 std::int8_t len{}; | |
11016 return get_number(input_format, len) && get_string(input_format, len, result); | |
11017 } | |
11018 | |
11019 case 'I': | |
11020 { | |
11021 std::int16_t len{}; | |
11022 return get_number(input_format, len) && get_string(input_format, len, result); | |
11023 } | |
11024 | |
11025 case 'l': | |
11026 { | |
11027 std::int32_t len{}; | |
11028 return get_number(input_format, len) && get_string(input_format, len, result); | |
11029 } | |
11030 | |
11031 case 'L': | |
11032 { | |
11033 std::int64_t len{}; | |
11034 return get_number(input_format, len) && get_string(input_format, len, result); | |
11035 } | |
11036 | |
11037 case 'u': | |
11038 { | |
11039 if (input_format != input_format_t::bjdata) | |
11040 { | |
11041 break; | |
11042 } | |
11043 std::uint16_t len{}; | |
11044 return get_number(input_format, len) && get_string(input_format, len, result); | |
11045 } | |
11046 | |
11047 case 'm': | |
11048 { | |
11049 if (input_format != input_format_t::bjdata) | |
11050 { | |
11051 break; | |
11052 } | |
11053 std::uint32_t len{}; | |
11054 return get_number(input_format, len) && get_string(input_format, len, result); | |
11055 } | |
11056 | |
11057 case 'M': | |
11058 { | |
11059 if (input_format != input_format_t::bjdata) | |
11060 { | |
11061 break; | |
11062 } | |
11063 std::uint64_t len{}; | |
11064 return get_number(input_format, len) && get_string(input_format, len, result); | |
11065 } | |
11066 | |
11067 default: | |
11068 break; | |
11069 } | |
11070 auto last_token = get_token_string(); | |
11071 std::string message; | |
11072 | |
11073 if (input_format != input_format_t::bjdata) | |
11074 { | |
11075 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; | |
11076 } | |
11077 else | |
11078 { | |
11079 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; | |
11080 } | |
11081 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); | |
11082 } | |
11083 | |
11084 /*! | |
11085 @param[out] dim an integer vector storing the ND array dimensions | |
11086 @return whether reading ND array size vector is successful | |
11087 */ | |
11088 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) | |
11089 { | |
11090 std::pair<std::size_t, char_int_type> size_and_type; | |
11091 size_t dimlen = 0; | |
11092 bool no_ndarray = true; | |
11093 | |
11094 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) | |
11095 { | |
11096 return false; | |
11097 } | |
11098 | |
11099 if (size_and_type.first != npos) | |
11100 { | |
11101 if (size_and_type.second != 0) | |
11102 { | |
11103 if (size_and_type.second != 'N') | |
11104 { | |
11105 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11106 { | |
11107 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) | |
11108 { | |
11109 return false; | |
11110 } | |
11111 dim.push_back(dimlen); | |
11112 } | |
11113 } | |
11114 } | |
11115 else | |
11116 { | |
11117 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11118 { | |
11119 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) | |
11120 { | |
11121 return false; | |
11122 } | |
11123 dim.push_back(dimlen); | |
11124 } | |
11125 } | |
11126 } | |
11127 else | |
11128 { | |
11129 while (current != ']') | |
11130 { | |
11131 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) | |
11132 { | |
11133 return false; | |
11134 } | |
11135 dim.push_back(dimlen); | |
11136 get_ignore_noop(); | |
11137 } | |
11138 } | |
11139 return true; | |
11140 } | |
11141 | |
11142 /*! | |
11143 @param[out] result determined size | |
11144 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector | |
11145 or ndarray dimension is not allowed; `false` means ndarray | |
11146 is allowed; for output, `true` means an ndarray is found; | |
11147 is_ndarray can only return `true` when its initial value | |
11148 is `false` | |
11149 @param[in] prefix type marker if already read, otherwise set to 0 | |
11150 | |
11151 @return whether size determination completed | |
11152 */ | |
11153 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) | |
11154 { | |
11155 if (prefix == 0) | |
11156 { | |
11157 prefix = get_ignore_noop(); | |
11158 } | |
11159 | |
11160 switch (prefix) | |
11161 { | |
11162 case 'U': | |
11163 { | |
11164 std::uint8_t number{}; | |
11165 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11166 { | |
11167 return false; | |
11168 } | |
11169 result = static_cast<std::size_t>(number); | |
11170 return true; | |
11171 } | |
11172 | |
11173 case 'i': | |
11174 { | |
11175 std::int8_t number{}; | |
11176 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11177 { | |
11178 return false; | |
11179 } | |
11180 if (number < 0) | |
11181 { | |
11182 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, | |
11183 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); | |
11184 } | |
11185 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char | |
11186 return true; | |
11187 } | |
11188 | |
11189 case 'I': | |
11190 { | |
11191 std::int16_t number{}; | |
11192 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11193 { | |
11194 return false; | |
11195 } | |
11196 if (number < 0) | |
11197 { | |
11198 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, | |
11199 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); | |
11200 } | |
11201 result = static_cast<std::size_t>(number); | |
11202 return true; | |
11203 } | |
11204 | |
11205 case 'l': | |
11206 { | |
11207 std::int32_t number{}; | |
11208 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11209 { | |
11210 return false; | |
11211 } | |
11212 if (number < 0) | |
11213 { | |
11214 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, | |
11215 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); | |
11216 } | |
11217 result = static_cast<std::size_t>(number); | |
11218 return true; | |
11219 } | |
11220 | |
11221 case 'L': | |
11222 { | |
11223 std::int64_t number{}; | |
11224 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11225 { | |
11226 return false; | |
11227 } | |
11228 if (number < 0) | |
11229 { | |
11230 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, | |
11231 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); | |
11232 } | |
11233 if (!value_in_range_of<std::size_t>(number)) | |
11234 { | |
11235 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, | |
11236 exception_message(input_format, "integer value overflow", "size"), nullptr)); | |
11237 } | |
11238 result = static_cast<std::size_t>(number); | |
11239 return true; | |
11240 } | |
11241 | |
11242 case 'u': | |
11243 { | |
11244 if (input_format != input_format_t::bjdata) | |
11245 { | |
11246 break; | |
11247 } | |
11248 std::uint16_t number{}; | |
11249 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11250 { | |
11251 return false; | |
11252 } | |
11253 result = static_cast<std::size_t>(number); | |
11254 return true; | |
11255 } | |
11256 | |
11257 case 'm': | |
11258 { | |
11259 if (input_format != input_format_t::bjdata) | |
11260 { | |
11261 break; | |
11262 } | |
11263 std::uint32_t number{}; | |
11264 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11265 { | |
11266 return false; | |
11267 } | |
11268 result = conditional_static_cast<std::size_t>(number); | |
11269 return true; | |
11270 } | |
11271 | |
11272 case 'M': | |
11273 { | |
11274 if (input_format != input_format_t::bjdata) | |
11275 { | |
11276 break; | |
11277 } | |
11278 std::uint64_t number{}; | |
11279 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) | |
11280 { | |
11281 return false; | |
11282 } | |
11283 if (!value_in_range_of<std::size_t>(number)) | |
11284 { | |
11285 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, | |
11286 exception_message(input_format, "integer value overflow", "size"), nullptr)); | |
11287 } | |
11288 result = detail::conditional_static_cast<std::size_t>(number); | |
11289 return true; | |
11290 } | |
11291 | |
11292 case '[': | |
11293 { | |
11294 if (input_format != input_format_t::bjdata) | |
11295 { | |
11296 break; | |
11297 } | |
11298 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array | |
11299 { | |
11300 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); | |
11301 } | |
11302 std::vector<size_t> dim; | |
11303 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) | |
11304 { | |
11305 return false; | |
11306 } | |
11307 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector | |
11308 { | |
11309 result = dim.at(dim.size() - 1); | |
11310 return true; | |
11311 } | |
11312 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format | |
11313 { | |
11314 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container | |
11315 { | |
11316 if ( i == 0 ) | |
11317 { | |
11318 result = 0; | |
11319 return true; | |
11320 } | |
11321 } | |
11322 | |
11323 string_t key = "_ArraySize_"; | |
11324 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) | |
11325 { | |
11326 return false; | |
11327 } | |
11328 result = 1; | |
11329 for (auto i : dim) | |
11330 { | |
11331 result *= i; | |
11332 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() | |
11333 { | |
11334 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); | |
11335 } | |
11336 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i)))) | |
11337 { | |
11338 return false; | |
11339 } | |
11340 } | |
11341 is_ndarray = true; | |
11342 return sax->end_array(); | |
11343 } | |
11344 result = 0; | |
11345 return true; | |
11346 } | |
11347 | |
11348 default: | |
11349 break; | |
11350 } | |
11351 auto last_token = get_token_string(); | |
11352 std::string message; | |
11353 | |
11354 if (input_format != input_format_t::bjdata) | |
11355 { | |
11356 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; | |
11357 } | |
11358 else | |
11359 { | |
11360 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; | |
11361 } | |
11362 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); | |
11363 } | |
11364 | |
11365 /*! | |
11366 @brief determine the type and size for a container | |
11367 | |
11368 In the optimized UBJSON format, a type and a size can be provided to allow | |
11369 for a more compact representation. | |
11370 | |
11371 @param[out] result pair of the size and the type | |
11372 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector | |
11373 | |
11374 @return whether pair creation completed | |
11375 */ | |
11376 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false) | |
11377 { | |
11378 result.first = npos; // size | |
11379 result.second = 0; // type | |
11380 bool is_ndarray = false; | |
11381 | |
11382 get_ignore_noop(); | |
11383 | |
11384 if (current == '$') | |
11385 { | |
11386 result.second = get(); // must not ignore 'N', because 'N' maybe the type | |
11387 if (input_format == input_format_t::bjdata | |
11388 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) | |
11389 { | |
11390 auto last_token = get_token_string(); | |
11391 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
11392 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); | |
11393 } | |
11394 | |
11395 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) | |
11396 { | |
11397 return false; | |
11398 } | |
11399 | |
11400 get_ignore_noop(); | |
11401 if (JSON_HEDLEY_UNLIKELY(current != '#')) | |
11402 { | |
11403 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) | |
11404 { | |
11405 return false; | |
11406 } | |
11407 auto last_token = get_token_string(); | |
11408 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
11409 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); | |
11410 } | |
11411 | |
11412 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); | |
11413 if (input_format == input_format_t::bjdata && is_ndarray) | |
11414 { | |
11415 if (inside_ndarray) | |
11416 { | |
11417 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, | |
11418 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); | |
11419 } | |
11420 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters | |
11421 } | |
11422 return is_error; | |
11423 } | |
11424 | |
11425 if (current == '#') | |
11426 { | |
11427 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); | |
11428 if (input_format == input_format_t::bjdata && is_ndarray) | |
11429 { | |
11430 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, | |
11431 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); | |
11432 } | |
11433 return is_error; | |
11434 } | |
11435 | |
11436 return true; | |
11437 } | |
11438 | |
11439 /*! | |
11440 @param prefix the previously read or set type prefix | |
11441 @return whether value creation completed | |
11442 */ | |
11443 bool get_ubjson_value(const char_int_type prefix) | |
11444 { | |
11445 switch (prefix) | |
11446 { | |
11447 case char_traits<char_type>::eof(): // EOF | |
11448 return unexpect_eof(input_format, "value"); | |
11449 | |
11450 case 'T': // true | |
11451 return sax->boolean(true); | |
11452 case 'F': // false | |
11453 return sax->boolean(false); | |
11454 | |
11455 case 'Z': // null | |
11456 return sax->null(); | |
11457 | |
11458 case 'U': | |
11459 { | |
11460 std::uint8_t number{}; | |
11461 return get_number(input_format, number) && sax->number_unsigned(number); | |
11462 } | |
11463 | |
11464 case 'i': | |
11465 { | |
11466 std::int8_t number{}; | |
11467 return get_number(input_format, number) && sax->number_integer(number); | |
11468 } | |
11469 | |
11470 case 'I': | |
11471 { | |
11472 std::int16_t number{}; | |
11473 return get_number(input_format, number) && sax->number_integer(number); | |
11474 } | |
11475 | |
11476 case 'l': | |
11477 { | |
11478 std::int32_t number{}; | |
11479 return get_number(input_format, number) && sax->number_integer(number); | |
11480 } | |
11481 | |
11482 case 'L': | |
11483 { | |
11484 std::int64_t number{}; | |
11485 return get_number(input_format, number) && sax->number_integer(number); | |
11486 } | |
11487 | |
11488 case 'u': | |
11489 { | |
11490 if (input_format != input_format_t::bjdata) | |
11491 { | |
11492 break; | |
11493 } | |
11494 std::uint16_t number{}; | |
11495 return get_number(input_format, number) && sax->number_unsigned(number); | |
11496 } | |
11497 | |
11498 case 'm': | |
11499 { | |
11500 if (input_format != input_format_t::bjdata) | |
11501 { | |
11502 break; | |
11503 } | |
11504 std::uint32_t number{}; | |
11505 return get_number(input_format, number) && sax->number_unsigned(number); | |
11506 } | |
11507 | |
11508 case 'M': | |
11509 { | |
11510 if (input_format != input_format_t::bjdata) | |
11511 { | |
11512 break; | |
11513 } | |
11514 std::uint64_t number{}; | |
11515 return get_number(input_format, number) && sax->number_unsigned(number); | |
11516 } | |
11517 | |
11518 case 'h': | |
11519 { | |
11520 if (input_format != input_format_t::bjdata) | |
11521 { | |
11522 break; | |
11523 } | |
11524 const auto byte1_raw = get(); | |
11525 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) | |
11526 { | |
11527 return false; | |
11528 } | |
11529 const auto byte2_raw = get(); | |
11530 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) | |
11531 { | |
11532 return false; | |
11533 } | |
11534 | |
11535 const auto byte1 = static_cast<unsigned char>(byte1_raw); | |
11536 const auto byte2 = static_cast<unsigned char>(byte2_raw); | |
11537 | |
11538 // code from RFC 7049, Appendix D, Figure 3: | |
11539 // As half-precision floating-point numbers were only added | |
11540 // to IEEE 754 in 2008, today's programming platforms often | |
11541 // still only have limited support for them. It is very | |
11542 // easy to include at least decoding support for them even | |
11543 // without such support. An example of a small decoder for | |
11544 // half-precision floating-point numbers in the C language | |
11545 // is shown in Fig. 3. | |
11546 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1); | |
11547 const double val = [&half] | |
11548 { | |
11549 const int exp = (half >> 10u) & 0x1Fu; | |
11550 const unsigned int mant = half & 0x3FFu; | |
11551 JSON_ASSERT(0 <= exp&& exp <= 32); | |
11552 JSON_ASSERT(mant <= 1024); | |
11553 switch (exp) | |
11554 { | |
11555 case 0: | |
11556 return std::ldexp(mant, -24); | |
11557 case 31: | |
11558 return (mant == 0) | |
11559 ? std::numeric_limits<double>::infinity() | |
11560 : std::numeric_limits<double>::quiet_NaN(); | |
11561 default: | |
11562 return std::ldexp(mant + 1024, exp - 25); | |
11563 } | |
11564 }(); | |
11565 return sax->number_float((half & 0x8000u) != 0 | |
11566 ? static_cast<number_float_t>(-val) | |
11567 : static_cast<number_float_t>(val), ""); | |
11568 } | |
11569 | |
11570 case 'd': | |
11571 { | |
11572 float number{}; | |
11573 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
11574 } | |
11575 | |
11576 case 'D': | |
11577 { | |
11578 double number{}; | |
11579 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); | |
11580 } | |
11581 | |
11582 case 'H': | |
11583 { | |
11584 return get_ubjson_high_precision_number(); | |
11585 } | |
11586 | |
11587 case 'C': // char | |
11588 { | |
11589 get(); | |
11590 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) | |
11591 { | |
11592 return false; | |
11593 } | |
11594 if (JSON_HEDLEY_UNLIKELY(current > 127)) | |
11595 { | |
11596 auto last_token = get_token_string(); | |
11597 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, | |
11598 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); | |
11599 } | |
11600 string_t s(1, static_cast<typename string_t::value_type>(current)); | |
11601 return sax->string(s); | |
11602 } | |
11603 | |
11604 case 'S': // string | |
11605 { | |
11606 string_t s; | |
11607 return get_ubjson_string(s) && sax->string(s); | |
11608 } | |
11609 | |
11610 case '[': // array | |
11611 return get_ubjson_array(); | |
11612 | |
11613 case '{': // object | |
11614 return get_ubjson_object(); | |
11615 | |
11616 default: // anything else | |
11617 break; | |
11618 } | |
11619 auto last_token = get_token_string(); | |
11620 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); | |
11621 } | |
11622 | |
11623 /*! | |
11624 @return whether array creation completed | |
11625 */ | |
11626 bool get_ubjson_array() | |
11627 { | |
11628 std::pair<std::size_t, char_int_type> size_and_type; | |
11629 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) | |
11630 { | |
11631 return false; | |
11632 } | |
11633 | |
11634 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): | |
11635 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} | |
11636 | |
11637 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) | |
11638 { | |
11639 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker | |
11640 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) | |
11641 { | |
11642 return p.first < t; | |
11643 }); | |
11644 string_t key = "_ArrayType_"; | |
11645 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) | |
11646 { | |
11647 auto last_token = get_token_string(); | |
11648 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
11649 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); | |
11650 } | |
11651 | |
11652 string_t type = it->second; // sax->string() takes a reference | |
11653 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) | |
11654 { | |
11655 return false; | |
11656 } | |
11657 | |
11658 if (size_and_type.second == 'C') | |
11659 { | |
11660 size_and_type.second = 'U'; | |
11661 } | |
11662 | |
11663 key = "_ArrayData_"; | |
11664 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) | |
11665 { | |
11666 return false; | |
11667 } | |
11668 | |
11669 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11670 { | |
11671 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) | |
11672 { | |
11673 return false; | |
11674 } | |
11675 } | |
11676 | |
11677 return (sax->end_array() && sax->end_object()); | |
11678 } | |
11679 | |
11680 if (size_and_type.first != npos) | |
11681 { | |
11682 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) | |
11683 { | |
11684 return false; | |
11685 } | |
11686 | |
11687 if (size_and_type.second != 0) | |
11688 { | |
11689 if (size_and_type.second != 'N') | |
11690 { | |
11691 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11692 { | |
11693 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) | |
11694 { | |
11695 return false; | |
11696 } | |
11697 } | |
11698 } | |
11699 } | |
11700 else | |
11701 { | |
11702 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11703 { | |
11704 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) | |
11705 { | |
11706 return false; | |
11707 } | |
11708 } | |
11709 } | |
11710 } | |
11711 else | |
11712 { | |
11713 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) | |
11714 { | |
11715 return false; | |
11716 } | |
11717 | |
11718 while (current != ']') | |
11719 { | |
11720 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) | |
11721 { | |
11722 return false; | |
11723 } | |
11724 get_ignore_noop(); | |
11725 } | |
11726 } | |
11727 | |
11728 return sax->end_array(); | |
11729 } | |
11730 | |
11731 /*! | |
11732 @return whether object creation completed | |
11733 */ | |
11734 bool get_ubjson_object() | |
11735 { | |
11736 std::pair<std::size_t, char_int_type> size_and_type; | |
11737 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) | |
11738 { | |
11739 return false; | |
11740 } | |
11741 | |
11742 // do not accept ND-array size in objects in BJData | |
11743 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) | |
11744 { | |
11745 auto last_token = get_token_string(); | |
11746 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, | |
11747 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); | |
11748 } | |
11749 | |
11750 string_t key; | |
11751 if (size_and_type.first != npos) | |
11752 { | |
11753 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) | |
11754 { | |
11755 return false; | |
11756 } | |
11757 | |
11758 if (size_and_type.second != 0) | |
11759 { | |
11760 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11761 { | |
11762 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) | |
11763 { | |
11764 return false; | |
11765 } | |
11766 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) | |
11767 { | |
11768 return false; | |
11769 } | |
11770 key.clear(); | |
11771 } | |
11772 } | |
11773 else | |
11774 { | |
11775 for (std::size_t i = 0; i < size_and_type.first; ++i) | |
11776 { | |
11777 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) | |
11778 { | |
11779 return false; | |
11780 } | |
11781 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) | |
11782 { | |
11783 return false; | |
11784 } | |
11785 key.clear(); | |
11786 } | |
11787 } | |
11788 } | |
11789 else | |
11790 { | |
11791 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) | |
11792 { | |
11793 return false; | |
11794 } | |
11795 | |
11796 while (current != '}') | |
11797 { | |
11798 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) | |
11799 { | |
11800 return false; | |
11801 } | |
11802 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) | |
11803 { | |
11804 return false; | |
11805 } | |
11806 get_ignore_noop(); | |
11807 key.clear(); | |
11808 } | |
11809 } | |
11810 | |
11811 return sax->end_object(); | |
11812 } | |
11813 | |
11814 // Note, no reader for UBJSON binary types is implemented because they do | |
11815 // not exist | |
11816 | |
11817 bool get_ubjson_high_precision_number() | |
11818 { | |
11819 // get size of following number string | |
11820 std::size_t size{}; | |
11821 bool no_ndarray = true; | |
11822 auto res = get_ubjson_size_value(size, no_ndarray); | |
11823 if (JSON_HEDLEY_UNLIKELY(!res)) | |
11824 { | |
11825 return res; | |
11826 } | |
11827 | |
11828 // get number string | |
11829 std::vector<char> number_vector; | |
11830 for (std::size_t i = 0; i < size; ++i) | |
11831 { | |
11832 get(); | |
11833 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) | |
11834 { | |
11835 return false; | |
11836 } | |
11837 number_vector.push_back(static_cast<char>(current)); | |
11838 } | |
11839 | |
11840 // parse number string | |
11841 using ia_type = decltype(detail::input_adapter(number_vector)); | |
11842 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false); | |
11843 const auto result_number = number_lexer.scan(); | |
11844 const auto number_string = number_lexer.get_token_string(); | |
11845 const auto result_remainder = number_lexer.scan(); | |
11846 | |
11847 using token_type = typename detail::lexer_base<BasicJsonType>::token_type; | |
11848 | |
11849 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) | |
11850 { | |
11851 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, | |
11852 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); | |
11853 } | |
11854 | |
11855 switch (result_number) | |
11856 { | |
11857 case token_type::value_integer: | |
11858 return sax->number_integer(number_lexer.get_number_integer()); | |
11859 case token_type::value_unsigned: | |
11860 return sax->number_unsigned(number_lexer.get_number_unsigned()); | |
11861 case token_type::value_float: | |
11862 return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); | |
11863 case token_type::uninitialized: | |
11864 case token_type::literal_true: | |
11865 case token_type::literal_false: | |
11866 case token_type::literal_null: | |
11867 case token_type::value_string: | |
11868 case token_type::begin_array: | |
11869 case token_type::begin_object: | |
11870 case token_type::end_array: | |
11871 case token_type::end_object: | |
11872 case token_type::name_separator: | |
11873 case token_type::value_separator: | |
11874 case token_type::parse_error: | |
11875 case token_type::end_of_input: | |
11876 case token_type::literal_or_value: | |
11877 default: | |
11878 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, | |
11879 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); | |
11880 } | |
11881 } | |
11882 | |
11883 /////////////////////// | |
11884 // Utility functions // | |
11885 /////////////////////// | |
11886 | |
11887 /*! | |
11888 @brief get next character from the input | |
11889 | |
11890 This function provides the interface to the used input adapter. It does | |
11891 not throw in case the input reached EOF, but returns a -'ve valued | |
11892 `char_traits<char_type>::eof()` in that case. | |
11893 | |
11894 @return character read from the input | |
11895 */ | |
11896 char_int_type get() | |
11897 { | |
11898 ++chars_read; | |
11899 return current = ia.get_character(); | |
11900 } | |
11901 | |
11902 /*! | |
11903 @return character read from the input after ignoring all 'N' entries | |
11904 */ | |
11905 char_int_type get_ignore_noop() | |
11906 { | |
11907 do | |
11908 { | |
11909 get(); | |
11910 } | |
11911 while (current == 'N'); | |
11912 | |
11913 return current; | |
11914 } | |
11915 | |
11916 /* | |
11917 @brief read a number from the input | |
11918 | |
11919 @tparam NumberType the type of the number | |
11920 @param[in] format the current format (for diagnostics) | |
11921 @param[out] result number of type @a NumberType | |
11922 | |
11923 @return whether conversion completed | |
11924 | |
11925 @note This function needs to respect the system's endianness, because | |
11926 bytes in CBOR, MessagePack, and UBJSON are stored in network order | |
11927 (big endian) and therefore need reordering on little endian systems. | |
11928 On the other hand, BSON and BJData use little endian and should reorder | |
11929 on big endian systems. | |
11930 */ | |
11931 template<typename NumberType, bool InputIsLittleEndian = false> | |
11932 bool get_number(const input_format_t format, NumberType& result) | |
11933 { | |
11934 // step 1: read input into array with system's byte order | |
11935 std::array<std::uint8_t, sizeof(NumberType)> vec{}; | |
11936 for (std::size_t i = 0; i < sizeof(NumberType); ++i) | |
11937 { | |
11938 get(); | |
11939 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) | |
11940 { | |
11941 return false; | |
11942 } | |
11943 | |
11944 // reverse byte order prior to conversion if necessary | |
11945 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) | |
11946 { | |
11947 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current); | |
11948 } | |
11949 else | |
11950 { | |
11951 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE | |
11952 } | |
11953 } | |
11954 | |
11955 // step 2: convert array into number of type T and return | |
11956 std::memcpy(&result, vec.data(), sizeof(NumberType)); | |
11957 return true; | |
11958 } | |
11959 | |
11960 /*! | |
11961 @brief create a string by reading characters from the input | |
11962 | |
11963 @tparam NumberType the type of the number | |
11964 @param[in] format the current format (for diagnostics) | |
11965 @param[in] len number of characters to read | |
11966 @param[out] result string created by reading @a len bytes | |
11967 | |
11968 @return whether string creation completed | |
11969 | |
11970 @note We can not reserve @a len bytes for the result, because @a len | |
11971 may be too large. Usually, @ref unexpect_eof() detects the end of | |
11972 the input before we run out of string memory. | |
11973 */ | |
11974 template<typename NumberType> | |
11975 bool get_string(const input_format_t format, | |
11976 const NumberType len, | |
11977 string_t& result) | |
11978 { | |
11979 bool success = true; | |
11980 for (NumberType i = 0; i < len; i++) | |
11981 { | |
11982 get(); | |
11983 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) | |
11984 { | |
11985 success = false; | |
11986 break; | |
11987 } | |
11988 result.push_back(static_cast<typename string_t::value_type>(current)); | |
11989 } | |
11990 return success; | |
11991 } | |
11992 | |
11993 /*! | |
11994 @brief create a byte array by reading bytes from the input | |
11995 | |
11996 @tparam NumberType the type of the number | |
11997 @param[in] format the current format (for diagnostics) | |
11998 @param[in] len number of bytes to read | |
11999 @param[out] result byte array created by reading @a len bytes | |
12000 | |
12001 @return whether byte array creation completed | |
12002 | |
12003 @note We can not reserve @a len bytes for the result, because @a len | |
12004 may be too large. Usually, @ref unexpect_eof() detects the end of | |
12005 the input before we run out of memory. | |
12006 */ | |
12007 template<typename NumberType> | |
12008 bool get_binary(const input_format_t format, | |
12009 const NumberType len, | |
12010 binary_t& result) | |
12011 { | |
12012 bool success = true; | |
12013 for (NumberType i = 0; i < len; i++) | |
12014 { | |
12015 get(); | |
12016 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) | |
12017 { | |
12018 success = false; | |
12019 break; | |
12020 } | |
12021 result.push_back(static_cast<std::uint8_t>(current)); | |
12022 } | |
12023 return success; | |
12024 } | |
12025 | |
12026 /*! | |
12027 @param[in] format the current format (for diagnostics) | |
12028 @param[in] context further context information (for diagnostics) | |
12029 @return whether the last read character is not EOF | |
12030 */ | |
12031 JSON_HEDLEY_NON_NULL(3) | |
12032 bool unexpect_eof(const input_format_t format, const char* context) const | |
12033 { | |
12034 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) | |
12035 { | |
12036 return sax->parse_error(chars_read, "<end of file>", | |
12037 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); | |
12038 } | |
12039 return true; | |
12040 } | |
12041 | |
12042 /*! | |
12043 @return a string representation of the last read byte | |
12044 */ | |
12045 std::string get_token_string() const | |
12046 { | |
12047 std::array<char, 3> cr{{}}; | |
12048 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
12049 return std::string{cr.data()}; | |
12050 } | |
12051 | |
12052 /*! | |
12053 @param[in] format the current format | |
12054 @param[in] detail a detailed error message | |
12055 @param[in] context further context information | |
12056 @return a message string to use in the parse_error exceptions | |
12057 */ | |
12058 std::string exception_message(const input_format_t format, | |
12059 const std::string& detail, | |
12060 const std::string& context) const | |
12061 { | |
12062 std::string error_msg = "syntax error while parsing "; | |
12063 | |
12064 switch (format) | |
12065 { | |
12066 case input_format_t::cbor: | |
12067 error_msg += "CBOR"; | |
12068 break; | |
12069 | |
12070 case input_format_t::msgpack: | |
12071 error_msg += "MessagePack"; | |
12072 break; | |
12073 | |
12074 case input_format_t::ubjson: | |
12075 error_msg += "UBJSON"; | |
12076 break; | |
12077 | |
12078 case input_format_t::bson: | |
12079 error_msg += "BSON"; | |
12080 break; | |
12081 | |
12082 case input_format_t::bjdata: | |
12083 error_msg += "BJData"; | |
12084 break; | |
12085 | |
12086 case input_format_t::json: // LCOV_EXCL_LINE | |
12087 default: // LCOV_EXCL_LINE | |
12088 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
12089 } | |
12090 | |
12091 return concat(error_msg, ' ', context, ": ", detail); | |
12092 } | |
12093 | |
12094 private: | |
12095 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1); | |
12096 | |
12097 /// input adapter | |
12098 InputAdapterType ia; | |
12099 | |
12100 /// the current character | |
12101 char_int_type current = char_traits<char_type>::eof(); | |
12102 | |
12103 /// the number of characters read | |
12104 std::size_t chars_read = 0; | |
12105 | |
12106 /// whether we can assume little endianness | |
12107 const bool is_little_endian = little_endianness(); | |
12108 | |
12109 /// input format | |
12110 const input_format_t input_format = input_format_t::json; | |
12111 | |
12112 /// the SAX parser | |
12113 json_sax_t* sax = nullptr; | |
12114 | |
12115 // excluded markers in bjdata optimized type | |
12116 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ | |
12117 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') | |
12118 | |
12119 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ | |
12120 make_array<bjd_type>( \ | |
12121 bjd_type{'C', "char"}, \ | |
12122 bjd_type{'D', "double"}, \ | |
12123 bjd_type{'I', "int16"}, \ | |
12124 bjd_type{'L', "int64"}, \ | |
12125 bjd_type{'M', "uint64"}, \ | |
12126 bjd_type{'U', "uint8"}, \ | |
12127 bjd_type{'d', "single"}, \ | |
12128 bjd_type{'i', "int8"}, \ | |
12129 bjd_type{'l', "int32"}, \ | |
12130 bjd_type{'m', "uint32"}, \ | |
12131 bjd_type{'u', "uint16"}) | |
12132 | |
12133 JSON_PRIVATE_UNLESS_TESTED: | |
12134 // lookup tables | |
12135 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) | |
12136 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = | |
12137 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; | |
12138 | |
12139 using bjd_type = std::pair<char_int_type, string_t>; | |
12140 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) | |
12141 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = | |
12142 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; | |
12143 | |
12144 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ | |
12145 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ | |
12146 }; | |
12147 | |
12148 #ifndef JSON_HAS_CPP_17 | |
12149 template<typename BasicJsonType, typename InputAdapterType, typename SAX> | |
12150 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos; | |
12151 #endif | |
12152 | |
12153 } // namespace detail | |
12154 NLOHMANN_JSON_NAMESPACE_END | |
12155 | |
12156 // #include <nlohmann/detail/input/input_adapters.hpp> | |
12157 | |
12158 // #include <nlohmann/detail/input/lexer.hpp> | |
12159 | |
12160 // #include <nlohmann/detail/input/parser.hpp> | |
12161 // __ _____ _____ _____ | |
12162 // __| | __| | | | JSON for Modern C++ | |
12163 // | | |__ | | | | | | version 3.11.3 | |
12164 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
12165 // | |
12166 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
12167 // SPDX-License-Identifier: MIT | |
12168 | |
12169 | |
12170 | |
12171 #include <cmath> // isfinite | |
12172 #include <cstdint> // uint8_t | |
12173 #include <functional> // function | |
12174 #include <string> // string | |
12175 #include <utility> // move | |
12176 #include <vector> // vector | |
12177 | |
12178 // #include <nlohmann/detail/exceptions.hpp> | |
12179 | |
12180 // #include <nlohmann/detail/input/input_adapters.hpp> | |
12181 | |
12182 // #include <nlohmann/detail/input/json_sax.hpp> | |
12183 | |
12184 // #include <nlohmann/detail/input/lexer.hpp> | |
12185 | |
12186 // #include <nlohmann/detail/macro_scope.hpp> | |
12187 | |
12188 // #include <nlohmann/detail/meta/is_sax.hpp> | |
12189 | |
12190 // #include <nlohmann/detail/string_concat.hpp> | |
12191 | |
12192 // #include <nlohmann/detail/value_t.hpp> | |
12193 | |
12194 | |
12195 NLOHMANN_JSON_NAMESPACE_BEGIN | |
12196 namespace detail | |
12197 { | |
12198 //////////// | |
12199 // parser // | |
12200 //////////// | |
12201 | |
12202 enum class parse_event_t : std::uint8_t | |
12203 { | |
12204 /// the parser read `{` and started to process a JSON object | |
12205 object_start, | |
12206 /// the parser read `}` and finished processing a JSON object | |
12207 object_end, | |
12208 /// the parser read `[` and started to process a JSON array | |
12209 array_start, | |
12210 /// the parser read `]` and finished processing a JSON array | |
12211 array_end, | |
12212 /// the parser read a key of a value in an object | |
12213 key, | |
12214 /// the parser finished reading a JSON value | |
12215 value | |
12216 }; | |
12217 | |
12218 template<typename BasicJsonType> | |
12219 using parser_callback_t = | |
12220 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; | |
12221 | |
12222 /*! | |
12223 @brief syntax analysis | |
12224 | |
12225 This class implements a recursive descent parser. | |
12226 */ | |
12227 template<typename BasicJsonType, typename InputAdapterType> | |
12228 class parser | |
12229 { | |
12230 using number_integer_t = typename BasicJsonType::number_integer_t; | |
12231 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
12232 using number_float_t = typename BasicJsonType::number_float_t; | |
12233 using string_t = typename BasicJsonType::string_t; | |
12234 using lexer_t = lexer<BasicJsonType, InputAdapterType>; | |
12235 using token_type = typename lexer_t::token_type; | |
12236 | |
12237 public: | |
12238 /// a parser reading from an input adapter | |
12239 explicit parser(InputAdapterType&& adapter, | |
12240 const parser_callback_t<BasicJsonType> cb = nullptr, | |
12241 const bool allow_exceptions_ = true, | |
12242 const bool skip_comments = false) | |
12243 : callback(cb) | |
12244 , m_lexer(std::move(adapter), skip_comments) | |
12245 , allow_exceptions(allow_exceptions_) | |
12246 { | |
12247 // read first token | |
12248 get_token(); | |
12249 } | |
12250 | |
12251 /*! | |
12252 @brief public parser interface | |
12253 | |
12254 @param[in] strict whether to expect the last token to be EOF | |
12255 @param[in,out] result parsed JSON value | |
12256 | |
12257 @throw parse_error.101 in case of an unexpected token | |
12258 @throw parse_error.102 if to_unicode fails or surrogate error | |
12259 @throw parse_error.103 if to_unicode fails | |
12260 */ | |
12261 void parse(const bool strict, BasicJsonType& result) | |
12262 { | |
12263 if (callback) | |
12264 { | |
12265 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); | |
12266 sax_parse_internal(&sdp); | |
12267 | |
12268 // in strict mode, input must be completely read | |
12269 if (strict && (get_token() != token_type::end_of_input)) | |
12270 { | |
12271 sdp.parse_error(m_lexer.get_position(), | |
12272 m_lexer.get_token_string(), | |
12273 parse_error::create(101, m_lexer.get_position(), | |
12274 exception_message(token_type::end_of_input, "value"), nullptr)); | |
12275 } | |
12276 | |
12277 // in case of an error, return discarded value | |
12278 if (sdp.is_errored()) | |
12279 { | |
12280 result = value_t::discarded; | |
12281 return; | |
12282 } | |
12283 | |
12284 // set top-level value to null if it was discarded by the callback | |
12285 // function | |
12286 if (result.is_discarded()) | |
12287 { | |
12288 result = nullptr; | |
12289 } | |
12290 } | |
12291 else | |
12292 { | |
12293 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); | |
12294 sax_parse_internal(&sdp); | |
12295 | |
12296 // in strict mode, input must be completely read | |
12297 if (strict && (get_token() != token_type::end_of_input)) | |
12298 { | |
12299 sdp.parse_error(m_lexer.get_position(), | |
12300 m_lexer.get_token_string(), | |
12301 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); | |
12302 } | |
12303 | |
12304 // in case of an error, return discarded value | |
12305 if (sdp.is_errored()) | |
12306 { | |
12307 result = value_t::discarded; | |
12308 return; | |
12309 } | |
12310 } | |
12311 | |
12312 result.assert_invariant(); | |
12313 } | |
12314 | |
12315 /*! | |
12316 @brief public accept interface | |
12317 | |
12318 @param[in] strict whether to expect the last token to be EOF | |
12319 @return whether the input is a proper JSON text | |
12320 */ | |
12321 bool accept(const bool strict = true) | |
12322 { | |
12323 json_sax_acceptor<BasicJsonType> sax_acceptor; | |
12324 return sax_parse(&sax_acceptor, strict); | |
12325 } | |
12326 | |
12327 template<typename SAX> | |
12328 JSON_HEDLEY_NON_NULL(2) | |
12329 bool sax_parse(SAX* sax, const bool strict = true) | |
12330 { | |
12331 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; | |
12332 const bool result = sax_parse_internal(sax); | |
12333 | |
12334 // strict mode: next byte must be EOF | |
12335 if (result && strict && (get_token() != token_type::end_of_input)) | |
12336 { | |
12337 return sax->parse_error(m_lexer.get_position(), | |
12338 m_lexer.get_token_string(), | |
12339 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); | |
12340 } | |
12341 | |
12342 return result; | |
12343 } | |
12344 | |
12345 private: | |
12346 template<typename SAX> | |
12347 JSON_HEDLEY_NON_NULL(2) | |
12348 bool sax_parse_internal(SAX* sax) | |
12349 { | |
12350 // stack to remember the hierarchy of structured values we are parsing | |
12351 // true = array; false = object | |
12352 std::vector<bool> states; | |
12353 // value to avoid a goto (see comment where set to true) | |
12354 bool skip_to_state_evaluation = false; | |
12355 | |
12356 while (true) | |
12357 { | |
12358 if (!skip_to_state_evaluation) | |
12359 { | |
12360 // invariant: get_token() was called before each iteration | |
12361 switch (last_token) | |
12362 { | |
12363 case token_type::begin_object: | |
12364 { | |
12365 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) | |
12366 { | |
12367 return false; | |
12368 } | |
12369 | |
12370 // closing } -> we are done | |
12371 if (get_token() == token_type::end_object) | |
12372 { | |
12373 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) | |
12374 { | |
12375 return false; | |
12376 } | |
12377 break; | |
12378 } | |
12379 | |
12380 // parse key | |
12381 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) | |
12382 { | |
12383 return sax->parse_error(m_lexer.get_position(), | |
12384 m_lexer.get_token_string(), | |
12385 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); | |
12386 } | |
12387 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) | |
12388 { | |
12389 return false; | |
12390 } | |
12391 | |
12392 // parse separator (:) | |
12393 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) | |
12394 { | |
12395 return sax->parse_error(m_lexer.get_position(), | |
12396 m_lexer.get_token_string(), | |
12397 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); | |
12398 } | |
12399 | |
12400 // remember we are now inside an object | |
12401 states.push_back(false); | |
12402 | |
12403 // parse values | |
12404 get_token(); | |
12405 continue; | |
12406 } | |
12407 | |
12408 case token_type::begin_array: | |
12409 { | |
12410 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) | |
12411 { | |
12412 return false; | |
12413 } | |
12414 | |
12415 // closing ] -> we are done | |
12416 if (get_token() == token_type::end_array) | |
12417 { | |
12418 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) | |
12419 { | |
12420 return false; | |
12421 } | |
12422 break; | |
12423 } | |
12424 | |
12425 // remember we are now inside an array | |
12426 states.push_back(true); | |
12427 | |
12428 // parse values (no need to call get_token) | |
12429 continue; | |
12430 } | |
12431 | |
12432 case token_type::value_float: | |
12433 { | |
12434 const auto res = m_lexer.get_number_float(); | |
12435 | |
12436 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) | |
12437 { | |
12438 return sax->parse_error(m_lexer.get_position(), | |
12439 m_lexer.get_token_string(), | |
12440 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); | |
12441 } | |
12442 | |
12443 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) | |
12444 { | |
12445 return false; | |
12446 } | |
12447 | |
12448 break; | |
12449 } | |
12450 | |
12451 case token_type::literal_false: | |
12452 { | |
12453 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) | |
12454 { | |
12455 return false; | |
12456 } | |
12457 break; | |
12458 } | |
12459 | |
12460 case token_type::literal_null: | |
12461 { | |
12462 if (JSON_HEDLEY_UNLIKELY(!sax->null())) | |
12463 { | |
12464 return false; | |
12465 } | |
12466 break; | |
12467 } | |
12468 | |
12469 case token_type::literal_true: | |
12470 { | |
12471 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) | |
12472 { | |
12473 return false; | |
12474 } | |
12475 break; | |
12476 } | |
12477 | |
12478 case token_type::value_integer: | |
12479 { | |
12480 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) | |
12481 { | |
12482 return false; | |
12483 } | |
12484 break; | |
12485 } | |
12486 | |
12487 case token_type::value_string: | |
12488 { | |
12489 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) | |
12490 { | |
12491 return false; | |
12492 } | |
12493 break; | |
12494 } | |
12495 | |
12496 case token_type::value_unsigned: | |
12497 { | |
12498 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) | |
12499 { | |
12500 return false; | |
12501 } | |
12502 break; | |
12503 } | |
12504 | |
12505 case token_type::parse_error: | |
12506 { | |
12507 // using "uninitialized" to avoid "expected" message | |
12508 return sax->parse_error(m_lexer.get_position(), | |
12509 m_lexer.get_token_string(), | |
12510 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); | |
12511 } | |
12512 case token_type::end_of_input: | |
12513 { | |
12514 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) | |
12515 { | |
12516 return sax->parse_error(m_lexer.get_position(), | |
12517 m_lexer.get_token_string(), | |
12518 parse_error::create(101, m_lexer.get_position(), | |
12519 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); | |
12520 } | |
12521 | |
12522 return sax->parse_error(m_lexer.get_position(), | |
12523 m_lexer.get_token_string(), | |
12524 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); | |
12525 } | |
12526 case token_type::uninitialized: | |
12527 case token_type::end_array: | |
12528 case token_type::end_object: | |
12529 case token_type::name_separator: | |
12530 case token_type::value_separator: | |
12531 case token_type::literal_or_value: | |
12532 default: // the last token was unexpected | |
12533 { | |
12534 return sax->parse_error(m_lexer.get_position(), | |
12535 m_lexer.get_token_string(), | |
12536 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); | |
12537 } | |
12538 } | |
12539 } | |
12540 else | |
12541 { | |
12542 skip_to_state_evaluation = false; | |
12543 } | |
12544 | |
12545 // we reached this line after we successfully parsed a value | |
12546 if (states.empty()) | |
12547 { | |
12548 // empty stack: we reached the end of the hierarchy: done | |
12549 return true; | |
12550 } | |
12551 | |
12552 if (states.back()) // array | |
12553 { | |
12554 // comma -> next value | |
12555 if (get_token() == token_type::value_separator) | |
12556 { | |
12557 // parse a new value | |
12558 get_token(); | |
12559 continue; | |
12560 } | |
12561 | |
12562 // closing ] | |
12563 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) | |
12564 { | |
12565 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) | |
12566 { | |
12567 return false; | |
12568 } | |
12569 | |
12570 // We are done with this array. Before we can parse a | |
12571 // new value, we need to evaluate the new state first. | |
12572 // By setting skip_to_state_evaluation to false, we | |
12573 // are effectively jumping to the beginning of this if. | |
12574 JSON_ASSERT(!states.empty()); | |
12575 states.pop_back(); | |
12576 skip_to_state_evaluation = true; | |
12577 continue; | |
12578 } | |
12579 | |
12580 return sax->parse_error(m_lexer.get_position(), | |
12581 m_lexer.get_token_string(), | |
12582 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); | |
12583 } | |
12584 | |
12585 // states.back() is false -> object | |
12586 | |
12587 // comma -> next value | |
12588 if (get_token() == token_type::value_separator) | |
12589 { | |
12590 // parse key | |
12591 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) | |
12592 { | |
12593 return sax->parse_error(m_lexer.get_position(), | |
12594 m_lexer.get_token_string(), | |
12595 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); | |
12596 } | |
12597 | |
12598 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) | |
12599 { | |
12600 return false; | |
12601 } | |
12602 | |
12603 // parse separator (:) | |
12604 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) | |
12605 { | |
12606 return sax->parse_error(m_lexer.get_position(), | |
12607 m_lexer.get_token_string(), | |
12608 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); | |
12609 } | |
12610 | |
12611 // parse values | |
12612 get_token(); | |
12613 continue; | |
12614 } | |
12615 | |
12616 // closing } | |
12617 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) | |
12618 { | |
12619 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) | |
12620 { | |
12621 return false; | |
12622 } | |
12623 | |
12624 // We are done with this object. Before we can parse a | |
12625 // new value, we need to evaluate the new state first. | |
12626 // By setting skip_to_state_evaluation to false, we | |
12627 // are effectively jumping to the beginning of this if. | |
12628 JSON_ASSERT(!states.empty()); | |
12629 states.pop_back(); | |
12630 skip_to_state_evaluation = true; | |
12631 continue; | |
12632 } | |
12633 | |
12634 return sax->parse_error(m_lexer.get_position(), | |
12635 m_lexer.get_token_string(), | |
12636 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); | |
12637 } | |
12638 } | |
12639 | |
12640 /// get next token from lexer | |
12641 token_type get_token() | |
12642 { | |
12643 return last_token = m_lexer.scan(); | |
12644 } | |
12645 | |
12646 std::string exception_message(const token_type expected, const std::string& context) | |
12647 { | |
12648 std::string error_msg = "syntax error "; | |
12649 | |
12650 if (!context.empty()) | |
12651 { | |
12652 error_msg += concat("while parsing ", context, ' '); | |
12653 } | |
12654 | |
12655 error_msg += "- "; | |
12656 | |
12657 if (last_token == token_type::parse_error) | |
12658 { | |
12659 error_msg += concat(m_lexer.get_error_message(), "; last read: '", | |
12660 m_lexer.get_token_string(), '\''); | |
12661 } | |
12662 else | |
12663 { | |
12664 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); | |
12665 } | |
12666 | |
12667 if (expected != token_type::uninitialized) | |
12668 { | |
12669 error_msg += concat("; expected ", lexer_t::token_type_name(expected)); | |
12670 } | |
12671 | |
12672 return error_msg; | |
12673 } | |
12674 | |
12675 private: | |
12676 /// callback function | |
12677 const parser_callback_t<BasicJsonType> callback = nullptr; | |
12678 /// the type of the last read token | |
12679 token_type last_token = token_type::uninitialized; | |
12680 /// the lexer | |
12681 lexer_t m_lexer; | |
12682 /// whether to throw exceptions in case of errors | |
12683 const bool allow_exceptions = true; | |
12684 }; | |
12685 | |
12686 } // namespace detail | |
12687 NLOHMANN_JSON_NAMESPACE_END | |
12688 | |
12689 // #include <nlohmann/detail/iterators/internal_iterator.hpp> | |
12690 // __ _____ _____ _____ | |
12691 // __| | __| | | | JSON for Modern C++ | |
12692 // | | |__ | | | | | | version 3.11.3 | |
12693 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
12694 // | |
12695 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
12696 // SPDX-License-Identifier: MIT | |
12697 | |
12698 | |
12699 | |
12700 // #include <nlohmann/detail/abi_macros.hpp> | |
12701 | |
12702 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> | |
12703 // __ _____ _____ _____ | |
12704 // __| | __| | | | JSON for Modern C++ | |
12705 // | | |__ | | | | | | version 3.11.3 | |
12706 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
12707 // | |
12708 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
12709 // SPDX-License-Identifier: MIT | |
12710 | |
12711 | |
12712 | |
12713 #include <cstddef> // ptrdiff_t | |
12714 #include <limits> // numeric_limits | |
12715 | |
12716 // #include <nlohmann/detail/macro_scope.hpp> | |
12717 | |
12718 | |
12719 NLOHMANN_JSON_NAMESPACE_BEGIN | |
12720 namespace detail | |
12721 { | |
12722 | |
12723 /* | |
12724 @brief an iterator for primitive JSON types | |
12725 | |
12726 This class models an iterator for primitive JSON types (boolean, number, | |
12727 string). It's only purpose is to allow the iterator/const_iterator classes | |
12728 to "iterate" over primitive values. Internally, the iterator is modeled by | |
12729 a `difference_type` variable. Value begin_value (`0`) models the begin, | |
12730 end_value (`1`) models past the end. | |
12731 */ | |
12732 class primitive_iterator_t | |
12733 { | |
12734 private: | |
12735 using difference_type = std::ptrdiff_t; | |
12736 static constexpr difference_type begin_value = 0; | |
12737 static constexpr difference_type end_value = begin_value + 1; | |
12738 | |
12739 JSON_PRIVATE_UNLESS_TESTED: | |
12740 /// iterator as signed integer type | |
12741 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); | |
12742 | |
12743 public: | |
12744 constexpr difference_type get_value() const noexcept | |
12745 { | |
12746 return m_it; | |
12747 } | |
12748 | |
12749 /// set iterator to a defined beginning | |
12750 void set_begin() noexcept | |
12751 { | |
12752 m_it = begin_value; | |
12753 } | |
12754 | |
12755 /// set iterator to a defined past the end | |
12756 void set_end() noexcept | |
12757 { | |
12758 m_it = end_value; | |
12759 } | |
12760 | |
12761 /// return whether the iterator can be dereferenced | |
12762 constexpr bool is_begin() const noexcept | |
12763 { | |
12764 return m_it == begin_value; | |
12765 } | |
12766 | |
12767 /// return whether the iterator is at end | |
12768 constexpr bool is_end() const noexcept | |
12769 { | |
12770 return m_it == end_value; | |
12771 } | |
12772 | |
12773 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | |
12774 { | |
12775 return lhs.m_it == rhs.m_it; | |
12776 } | |
12777 | |
12778 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | |
12779 { | |
12780 return lhs.m_it < rhs.m_it; | |
12781 } | |
12782 | |
12783 primitive_iterator_t operator+(difference_type n) noexcept | |
12784 { | |
12785 auto result = *this; | |
12786 result += n; | |
12787 return result; | |
12788 } | |
12789 | |
12790 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept | |
12791 { | |
12792 return lhs.m_it - rhs.m_it; | |
12793 } | |
12794 | |
12795 primitive_iterator_t& operator++() noexcept | |
12796 { | |
12797 ++m_it; | |
12798 return *this; | |
12799 } | |
12800 | |
12801 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) | |
12802 { | |
12803 auto result = *this; | |
12804 ++m_it; | |
12805 return result; | |
12806 } | |
12807 | |
12808 primitive_iterator_t& operator--() noexcept | |
12809 { | |
12810 --m_it; | |
12811 return *this; | |
12812 } | |
12813 | |
12814 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) | |
12815 { | |
12816 auto result = *this; | |
12817 --m_it; | |
12818 return result; | |
12819 } | |
12820 | |
12821 primitive_iterator_t& operator+=(difference_type n) noexcept | |
12822 { | |
12823 m_it += n; | |
12824 return *this; | |
12825 } | |
12826 | |
12827 primitive_iterator_t& operator-=(difference_type n) noexcept | |
12828 { | |
12829 m_it -= n; | |
12830 return *this; | |
12831 } | |
12832 }; | |
12833 | |
12834 } // namespace detail | |
12835 NLOHMANN_JSON_NAMESPACE_END | |
12836 | |
12837 | |
12838 NLOHMANN_JSON_NAMESPACE_BEGIN | |
12839 namespace detail | |
12840 { | |
12841 | |
12842 /*! | |
12843 @brief an iterator value | |
12844 | |
12845 @note This structure could easily be a union, but MSVC currently does not allow | |
12846 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. | |
12847 */ | |
12848 template<typename BasicJsonType> struct internal_iterator | |
12849 { | |
12850 /// iterator for JSON objects | |
12851 typename BasicJsonType::object_t::iterator object_iterator {}; | |
12852 /// iterator for JSON arrays | |
12853 typename BasicJsonType::array_t::iterator array_iterator {}; | |
12854 /// generic iterator for all other types | |
12855 primitive_iterator_t primitive_iterator {}; | |
12856 }; | |
12857 | |
12858 } // namespace detail | |
12859 NLOHMANN_JSON_NAMESPACE_END | |
12860 | |
12861 // #include <nlohmann/detail/iterators/iter_impl.hpp> | |
12862 // __ _____ _____ _____ | |
12863 // __| | __| | | | JSON for Modern C++ | |
12864 // | | |__ | | | | | | version 3.11.3 | |
12865 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
12866 // | |
12867 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
12868 // SPDX-License-Identifier: MIT | |
12869 | |
12870 | |
12871 | |
12872 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next | |
12873 #include <type_traits> // conditional, is_const, remove_const | |
12874 | |
12875 // #include <nlohmann/detail/exceptions.hpp> | |
12876 | |
12877 // #include <nlohmann/detail/iterators/internal_iterator.hpp> | |
12878 | |
12879 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> | |
12880 | |
12881 // #include <nlohmann/detail/macro_scope.hpp> | |
12882 | |
12883 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
12884 | |
12885 // #include <nlohmann/detail/meta/type_traits.hpp> | |
12886 | |
12887 // #include <nlohmann/detail/value_t.hpp> | |
12888 | |
12889 | |
12890 NLOHMANN_JSON_NAMESPACE_BEGIN | |
12891 namespace detail | |
12892 { | |
12893 | |
12894 // forward declare, to be able to friend it later on | |
12895 template<typename IteratorType> class iteration_proxy; | |
12896 template<typename IteratorType> class iteration_proxy_value; | |
12897 | |
12898 /*! | |
12899 @brief a template for a bidirectional iterator for the @ref basic_json class | |
12900 This class implements a both iterators (iterator and const_iterator) for the | |
12901 @ref basic_json class. | |
12902 @note An iterator is called *initialized* when a pointer to a JSON value has | |
12903 been set (e.g., by a constructor or a copy assignment). If the iterator is | |
12904 default-constructed, it is *uninitialized* and most methods are undefined. | |
12905 **The library uses assertions to detect calls on uninitialized iterators.** | |
12906 @requirement The class satisfies the following concept requirements: | |
12907 - | |
12908 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): | |
12909 The iterator that can be moved can be moved in both directions (i.e. | |
12910 incremented and decremented). | |
12911 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional | |
12912 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) | |
12913 */ | |
12914 template<typename BasicJsonType> | |
12915 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) | |
12916 { | |
12917 /// the iterator with BasicJsonType of different const-ness | |
12918 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; | |
12919 /// allow basic_json to access private members | |
12920 friend other_iter_impl; | |
12921 friend BasicJsonType; | |
12922 friend iteration_proxy<iter_impl>; | |
12923 friend iteration_proxy_value<iter_impl>; | |
12924 | |
12925 using object_t = typename BasicJsonType::object_t; | |
12926 using array_t = typename BasicJsonType::array_t; | |
12927 // make sure BasicJsonType is basic_json or const basic_json | |
12928 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, | |
12929 "iter_impl only accepts (const) basic_json"); | |
12930 // superficial check for the LegacyBidirectionalIterator named requirement | |
12931 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value | |
12932 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value, | |
12933 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); | |
12934 | |
12935 public: | |
12936 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. | |
12937 /// The C++ Standard has never required user-defined iterators to derive from std::iterator. | |
12938 /// A user-defined iterator should provide publicly accessible typedefs named | |
12939 /// iterator_category, value_type, difference_type, pointer, and reference. | |
12940 /// Note that value_type is required to be non-const, even for constant iterators. | |
12941 using iterator_category = std::bidirectional_iterator_tag; | |
12942 | |
12943 /// the type of the values when the iterator is dereferenced | |
12944 using value_type = typename BasicJsonType::value_type; | |
12945 /// a type to represent differences between iterators | |
12946 using difference_type = typename BasicJsonType::difference_type; | |
12947 /// defines a pointer to the type iterated over (value_type) | |
12948 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, | |
12949 typename BasicJsonType::const_pointer, | |
12950 typename BasicJsonType::pointer>::type; | |
12951 /// defines a reference to the type iterated over (value_type) | |
12952 using reference = | |
12953 typename std::conditional<std::is_const<BasicJsonType>::value, | |
12954 typename BasicJsonType::const_reference, | |
12955 typename BasicJsonType::reference>::type; | |
12956 | |
12957 iter_impl() = default; | |
12958 ~iter_impl() = default; | |
12959 iter_impl(iter_impl&&) noexcept = default; | |
12960 iter_impl& operator=(iter_impl&&) noexcept = default; | |
12961 | |
12962 /*! | |
12963 @brief constructor for a given JSON instance | |
12964 @param[in] object pointer to a JSON object for this iterator | |
12965 @pre object != nullptr | |
12966 @post The iterator is initialized; i.e. `m_object != nullptr`. | |
12967 */ | |
12968 explicit iter_impl(pointer object) noexcept : m_object(object) | |
12969 { | |
12970 JSON_ASSERT(m_object != nullptr); | |
12971 | |
12972 switch (m_object->m_data.m_type) | |
12973 { | |
12974 case value_t::object: | |
12975 { | |
12976 m_it.object_iterator = typename object_t::iterator(); | |
12977 break; | |
12978 } | |
12979 | |
12980 case value_t::array: | |
12981 { | |
12982 m_it.array_iterator = typename array_t::iterator(); | |
12983 break; | |
12984 } | |
12985 | |
12986 case value_t::null: | |
12987 case value_t::string: | |
12988 case value_t::boolean: | |
12989 case value_t::number_integer: | |
12990 case value_t::number_unsigned: | |
12991 case value_t::number_float: | |
12992 case value_t::binary: | |
12993 case value_t::discarded: | |
12994 default: | |
12995 { | |
12996 m_it.primitive_iterator = primitive_iterator_t(); | |
12997 break; | |
12998 } | |
12999 } | |
13000 } | |
13001 | |
13002 /*! | |
13003 @note The conventional copy constructor and copy assignment are implicitly | |
13004 defined. Combined with the following converting constructor and | |
13005 assignment, they support: (1) copy from iterator to iterator, (2) | |
13006 copy from const iterator to const iterator, and (3) conversion from | |
13007 iterator to const iterator. However conversion from const iterator | |
13008 to iterator is not defined. | |
13009 */ | |
13010 | |
13011 /*! | |
13012 @brief const copy constructor | |
13013 @param[in] other const iterator to copy from | |
13014 @note This copy constructor had to be defined explicitly to circumvent a bug | |
13015 occurring on msvc v19.0 compiler (VS 2015) debug build. For more | |
13016 information refer to: https://github.com/nlohmann/json/issues/1608 | |
13017 */ | |
13018 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept | |
13019 : m_object(other.m_object), m_it(other.m_it) | |
13020 {} | |
13021 | |
13022 /*! | |
13023 @brief converting assignment | |
13024 @param[in] other const iterator to copy from | |
13025 @return const/non-const iterator | |
13026 @note It is not checked whether @a other is initialized. | |
13027 */ | |
13028 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept | |
13029 { | |
13030 if (&other != this) | |
13031 { | |
13032 m_object = other.m_object; | |
13033 m_it = other.m_it; | |
13034 } | |
13035 return *this; | |
13036 } | |
13037 | |
13038 /*! | |
13039 @brief converting constructor | |
13040 @param[in] other non-const iterator to copy from | |
13041 @note It is not checked whether @a other is initialized. | |
13042 */ | |
13043 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept | |
13044 : m_object(other.m_object), m_it(other.m_it) | |
13045 {} | |
13046 | |
13047 /*! | |
13048 @brief converting assignment | |
13049 @param[in] other non-const iterator to copy from | |
13050 @return const/non-const iterator | |
13051 @note It is not checked whether @a other is initialized. | |
13052 */ | |
13053 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp) | |
13054 { | |
13055 m_object = other.m_object; | |
13056 m_it = other.m_it; | |
13057 return *this; | |
13058 } | |
13059 | |
13060 JSON_PRIVATE_UNLESS_TESTED: | |
13061 /*! | |
13062 @brief set the iterator to the first value | |
13063 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13064 */ | |
13065 void set_begin() noexcept | |
13066 { | |
13067 JSON_ASSERT(m_object != nullptr); | |
13068 | |
13069 switch (m_object->m_data.m_type) | |
13070 { | |
13071 case value_t::object: | |
13072 { | |
13073 m_it.object_iterator = m_object->m_data.m_value.object->begin(); | |
13074 break; | |
13075 } | |
13076 | |
13077 case value_t::array: | |
13078 { | |
13079 m_it.array_iterator = m_object->m_data.m_value.array->begin(); | |
13080 break; | |
13081 } | |
13082 | |
13083 case value_t::null: | |
13084 { | |
13085 // set to end so begin()==end() is true: null is empty | |
13086 m_it.primitive_iterator.set_end(); | |
13087 break; | |
13088 } | |
13089 | |
13090 case value_t::string: | |
13091 case value_t::boolean: | |
13092 case value_t::number_integer: | |
13093 case value_t::number_unsigned: | |
13094 case value_t::number_float: | |
13095 case value_t::binary: | |
13096 case value_t::discarded: | |
13097 default: | |
13098 { | |
13099 m_it.primitive_iterator.set_begin(); | |
13100 break; | |
13101 } | |
13102 } | |
13103 } | |
13104 | |
13105 /*! | |
13106 @brief set the iterator past the last value | |
13107 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13108 */ | |
13109 void set_end() noexcept | |
13110 { | |
13111 JSON_ASSERT(m_object != nullptr); | |
13112 | |
13113 switch (m_object->m_data.m_type) | |
13114 { | |
13115 case value_t::object: | |
13116 { | |
13117 m_it.object_iterator = m_object->m_data.m_value.object->end(); | |
13118 break; | |
13119 } | |
13120 | |
13121 case value_t::array: | |
13122 { | |
13123 m_it.array_iterator = m_object->m_data.m_value.array->end(); | |
13124 break; | |
13125 } | |
13126 | |
13127 case value_t::null: | |
13128 case value_t::string: | |
13129 case value_t::boolean: | |
13130 case value_t::number_integer: | |
13131 case value_t::number_unsigned: | |
13132 case value_t::number_float: | |
13133 case value_t::binary: | |
13134 case value_t::discarded: | |
13135 default: | |
13136 { | |
13137 m_it.primitive_iterator.set_end(); | |
13138 break; | |
13139 } | |
13140 } | |
13141 } | |
13142 | |
13143 public: | |
13144 /*! | |
13145 @brief return a reference to the value pointed to by the iterator | |
13146 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13147 */ | |
13148 reference operator*() const | |
13149 { | |
13150 JSON_ASSERT(m_object != nullptr); | |
13151 | |
13152 switch (m_object->m_data.m_type) | |
13153 { | |
13154 case value_t::object: | |
13155 { | |
13156 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); | |
13157 return m_it.object_iterator->second; | |
13158 } | |
13159 | |
13160 case value_t::array: | |
13161 { | |
13162 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); | |
13163 return *m_it.array_iterator; | |
13164 } | |
13165 | |
13166 case value_t::null: | |
13167 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | |
13168 | |
13169 case value_t::string: | |
13170 case value_t::boolean: | |
13171 case value_t::number_integer: | |
13172 case value_t::number_unsigned: | |
13173 case value_t::number_float: | |
13174 case value_t::binary: | |
13175 case value_t::discarded: | |
13176 default: | |
13177 { | |
13178 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) | |
13179 { | |
13180 return *m_object; | |
13181 } | |
13182 | |
13183 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | |
13184 } | |
13185 } | |
13186 } | |
13187 | |
13188 /*! | |
13189 @brief dereference the iterator | |
13190 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13191 */ | |
13192 pointer operator->() const | |
13193 { | |
13194 JSON_ASSERT(m_object != nullptr); | |
13195 | |
13196 switch (m_object->m_data.m_type) | |
13197 { | |
13198 case value_t::object: | |
13199 { | |
13200 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); | |
13201 return &(m_it.object_iterator->second); | |
13202 } | |
13203 | |
13204 case value_t::array: | |
13205 { | |
13206 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); | |
13207 return &*m_it.array_iterator; | |
13208 } | |
13209 | |
13210 case value_t::null: | |
13211 case value_t::string: | |
13212 case value_t::boolean: | |
13213 case value_t::number_integer: | |
13214 case value_t::number_unsigned: | |
13215 case value_t::number_float: | |
13216 case value_t::binary: | |
13217 case value_t::discarded: | |
13218 default: | |
13219 { | |
13220 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) | |
13221 { | |
13222 return m_object; | |
13223 } | |
13224 | |
13225 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | |
13226 } | |
13227 } | |
13228 } | |
13229 | |
13230 /*! | |
13231 @brief post-increment (it++) | |
13232 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13233 */ | |
13234 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) | |
13235 { | |
13236 auto result = *this; | |
13237 ++(*this); | |
13238 return result; | |
13239 } | |
13240 | |
13241 /*! | |
13242 @brief pre-increment (++it) | |
13243 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13244 */ | |
13245 iter_impl& operator++() | |
13246 { | |
13247 JSON_ASSERT(m_object != nullptr); | |
13248 | |
13249 switch (m_object->m_data.m_type) | |
13250 { | |
13251 case value_t::object: | |
13252 { | |
13253 std::advance(m_it.object_iterator, 1); | |
13254 break; | |
13255 } | |
13256 | |
13257 case value_t::array: | |
13258 { | |
13259 std::advance(m_it.array_iterator, 1); | |
13260 break; | |
13261 } | |
13262 | |
13263 case value_t::null: | |
13264 case value_t::string: | |
13265 case value_t::boolean: | |
13266 case value_t::number_integer: | |
13267 case value_t::number_unsigned: | |
13268 case value_t::number_float: | |
13269 case value_t::binary: | |
13270 case value_t::discarded: | |
13271 default: | |
13272 { | |
13273 ++m_it.primitive_iterator; | |
13274 break; | |
13275 } | |
13276 } | |
13277 | |
13278 return *this; | |
13279 } | |
13280 | |
13281 /*! | |
13282 @brief post-decrement (it--) | |
13283 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13284 */ | |
13285 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) | |
13286 { | |
13287 auto result = *this; | |
13288 --(*this); | |
13289 return result; | |
13290 } | |
13291 | |
13292 /*! | |
13293 @brief pre-decrement (--it) | |
13294 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13295 */ | |
13296 iter_impl& operator--() | |
13297 { | |
13298 JSON_ASSERT(m_object != nullptr); | |
13299 | |
13300 switch (m_object->m_data.m_type) | |
13301 { | |
13302 case value_t::object: | |
13303 { | |
13304 std::advance(m_it.object_iterator, -1); | |
13305 break; | |
13306 } | |
13307 | |
13308 case value_t::array: | |
13309 { | |
13310 std::advance(m_it.array_iterator, -1); | |
13311 break; | |
13312 } | |
13313 | |
13314 case value_t::null: | |
13315 case value_t::string: | |
13316 case value_t::boolean: | |
13317 case value_t::number_integer: | |
13318 case value_t::number_unsigned: | |
13319 case value_t::number_float: | |
13320 case value_t::binary: | |
13321 case value_t::discarded: | |
13322 default: | |
13323 { | |
13324 --m_it.primitive_iterator; | |
13325 break; | |
13326 } | |
13327 } | |
13328 | |
13329 return *this; | |
13330 } | |
13331 | |
13332 /*! | |
13333 @brief comparison: equal | |
13334 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13335 */ | |
13336 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > | |
13337 bool operator==(const IterImpl& other) const | |
13338 { | |
13339 // if objects are not the same, the comparison is undefined | |
13340 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) | |
13341 { | |
13342 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); | |
13343 } | |
13344 | |
13345 JSON_ASSERT(m_object != nullptr); | |
13346 | |
13347 switch (m_object->m_data.m_type) | |
13348 { | |
13349 case value_t::object: | |
13350 return (m_it.object_iterator == other.m_it.object_iterator); | |
13351 | |
13352 case value_t::array: | |
13353 return (m_it.array_iterator == other.m_it.array_iterator); | |
13354 | |
13355 case value_t::null: | |
13356 case value_t::string: | |
13357 case value_t::boolean: | |
13358 case value_t::number_integer: | |
13359 case value_t::number_unsigned: | |
13360 case value_t::number_float: | |
13361 case value_t::binary: | |
13362 case value_t::discarded: | |
13363 default: | |
13364 return (m_it.primitive_iterator == other.m_it.primitive_iterator); | |
13365 } | |
13366 } | |
13367 | |
13368 /*! | |
13369 @brief comparison: not equal | |
13370 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13371 */ | |
13372 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > | |
13373 bool operator!=(const IterImpl& other) const | |
13374 { | |
13375 return !operator==(other); | |
13376 } | |
13377 | |
13378 /*! | |
13379 @brief comparison: smaller | |
13380 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13381 */ | |
13382 bool operator<(const iter_impl& other) const | |
13383 { | |
13384 // if objects are not the same, the comparison is undefined | |
13385 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) | |
13386 { | |
13387 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); | |
13388 } | |
13389 | |
13390 JSON_ASSERT(m_object != nullptr); | |
13391 | |
13392 switch (m_object->m_data.m_type) | |
13393 { | |
13394 case value_t::object: | |
13395 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); | |
13396 | |
13397 case value_t::array: | |
13398 return (m_it.array_iterator < other.m_it.array_iterator); | |
13399 | |
13400 case value_t::null: | |
13401 case value_t::string: | |
13402 case value_t::boolean: | |
13403 case value_t::number_integer: | |
13404 case value_t::number_unsigned: | |
13405 case value_t::number_float: | |
13406 case value_t::binary: | |
13407 case value_t::discarded: | |
13408 default: | |
13409 return (m_it.primitive_iterator < other.m_it.primitive_iterator); | |
13410 } | |
13411 } | |
13412 | |
13413 /*! | |
13414 @brief comparison: less than or equal | |
13415 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13416 */ | |
13417 bool operator<=(const iter_impl& other) const | |
13418 { | |
13419 return !other.operator < (*this); | |
13420 } | |
13421 | |
13422 /*! | |
13423 @brief comparison: greater than | |
13424 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13425 */ | |
13426 bool operator>(const iter_impl& other) const | |
13427 { | |
13428 return !operator<=(other); | |
13429 } | |
13430 | |
13431 /*! | |
13432 @brief comparison: greater than or equal | |
13433 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13434 */ | |
13435 bool operator>=(const iter_impl& other) const | |
13436 { | |
13437 return !operator<(other); | |
13438 } | |
13439 | |
13440 /*! | |
13441 @brief add to iterator | |
13442 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13443 */ | |
13444 iter_impl& operator+=(difference_type i) | |
13445 { | |
13446 JSON_ASSERT(m_object != nullptr); | |
13447 | |
13448 switch (m_object->m_data.m_type) | |
13449 { | |
13450 case value_t::object: | |
13451 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); | |
13452 | |
13453 case value_t::array: | |
13454 { | |
13455 std::advance(m_it.array_iterator, i); | |
13456 break; | |
13457 } | |
13458 | |
13459 case value_t::null: | |
13460 case value_t::string: | |
13461 case value_t::boolean: | |
13462 case value_t::number_integer: | |
13463 case value_t::number_unsigned: | |
13464 case value_t::number_float: | |
13465 case value_t::binary: | |
13466 case value_t::discarded: | |
13467 default: | |
13468 { | |
13469 m_it.primitive_iterator += i; | |
13470 break; | |
13471 } | |
13472 } | |
13473 | |
13474 return *this; | |
13475 } | |
13476 | |
13477 /*! | |
13478 @brief subtract from iterator | |
13479 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13480 */ | |
13481 iter_impl& operator-=(difference_type i) | |
13482 { | |
13483 return operator+=(-i); | |
13484 } | |
13485 | |
13486 /*! | |
13487 @brief add to iterator | |
13488 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13489 */ | |
13490 iter_impl operator+(difference_type i) const | |
13491 { | |
13492 auto result = *this; | |
13493 result += i; | |
13494 return result; | |
13495 } | |
13496 | |
13497 /*! | |
13498 @brief addition of distance and iterator | |
13499 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13500 */ | |
13501 friend iter_impl operator+(difference_type i, const iter_impl& it) | |
13502 { | |
13503 auto result = it; | |
13504 result += i; | |
13505 return result; | |
13506 } | |
13507 | |
13508 /*! | |
13509 @brief subtract from iterator | |
13510 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13511 */ | |
13512 iter_impl operator-(difference_type i) const | |
13513 { | |
13514 auto result = *this; | |
13515 result -= i; | |
13516 return result; | |
13517 } | |
13518 | |
13519 /*! | |
13520 @brief return difference | |
13521 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13522 */ | |
13523 difference_type operator-(const iter_impl& other) const | |
13524 { | |
13525 JSON_ASSERT(m_object != nullptr); | |
13526 | |
13527 switch (m_object->m_data.m_type) | |
13528 { | |
13529 case value_t::object: | |
13530 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); | |
13531 | |
13532 case value_t::array: | |
13533 return m_it.array_iterator - other.m_it.array_iterator; | |
13534 | |
13535 case value_t::null: | |
13536 case value_t::string: | |
13537 case value_t::boolean: | |
13538 case value_t::number_integer: | |
13539 case value_t::number_unsigned: | |
13540 case value_t::number_float: | |
13541 case value_t::binary: | |
13542 case value_t::discarded: | |
13543 default: | |
13544 return m_it.primitive_iterator - other.m_it.primitive_iterator; | |
13545 } | |
13546 } | |
13547 | |
13548 /*! | |
13549 @brief access to successor | |
13550 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13551 */ | |
13552 reference operator[](difference_type n) const | |
13553 { | |
13554 JSON_ASSERT(m_object != nullptr); | |
13555 | |
13556 switch (m_object->m_data.m_type) | |
13557 { | |
13558 case value_t::object: | |
13559 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); | |
13560 | |
13561 case value_t::array: | |
13562 return *std::next(m_it.array_iterator, n); | |
13563 | |
13564 case value_t::null: | |
13565 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | |
13566 | |
13567 case value_t::string: | |
13568 case value_t::boolean: | |
13569 case value_t::number_integer: | |
13570 case value_t::number_unsigned: | |
13571 case value_t::number_float: | |
13572 case value_t::binary: | |
13573 case value_t::discarded: | |
13574 default: | |
13575 { | |
13576 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) | |
13577 { | |
13578 return *m_object; | |
13579 } | |
13580 | |
13581 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); | |
13582 } | |
13583 } | |
13584 } | |
13585 | |
13586 /*! | |
13587 @brief return the key of an object iterator | |
13588 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13589 */ | |
13590 const typename object_t::key_type& key() const | |
13591 { | |
13592 JSON_ASSERT(m_object != nullptr); | |
13593 | |
13594 if (JSON_HEDLEY_LIKELY(m_object->is_object())) | |
13595 { | |
13596 return m_it.object_iterator->first; | |
13597 } | |
13598 | |
13599 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); | |
13600 } | |
13601 | |
13602 /*! | |
13603 @brief return the value of an iterator | |
13604 @pre The iterator is initialized; i.e. `m_object != nullptr`. | |
13605 */ | |
13606 reference value() const | |
13607 { | |
13608 return operator*(); | |
13609 } | |
13610 | |
13611 JSON_PRIVATE_UNLESS_TESTED: | |
13612 /// associated JSON instance | |
13613 pointer m_object = nullptr; | |
13614 /// the actual iterator of the associated instance | |
13615 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {}; | |
13616 }; | |
13617 | |
13618 } // namespace detail | |
13619 NLOHMANN_JSON_NAMESPACE_END | |
13620 | |
13621 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> | |
13622 | |
13623 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> | |
13624 // __ _____ _____ _____ | |
13625 // __| | __| | | | JSON for Modern C++ | |
13626 // | | |__ | | | | | | version 3.11.3 | |
13627 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
13628 // | |
13629 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
13630 // SPDX-License-Identifier: MIT | |
13631 | |
13632 | |
13633 | |
13634 #include <cstddef> // ptrdiff_t | |
13635 #include <iterator> // reverse_iterator | |
13636 #include <utility> // declval | |
13637 | |
13638 // #include <nlohmann/detail/abi_macros.hpp> | |
13639 | |
13640 | |
13641 NLOHMANN_JSON_NAMESPACE_BEGIN | |
13642 namespace detail | |
13643 { | |
13644 | |
13645 ////////////////////// | |
13646 // reverse_iterator // | |
13647 ////////////////////// | |
13648 | |
13649 /*! | |
13650 @brief a template for a reverse iterator class | |
13651 | |
13652 @tparam Base the base iterator type to reverse. Valid types are @ref | |
13653 iterator (to create @ref reverse_iterator) and @ref const_iterator (to | |
13654 create @ref const_reverse_iterator). | |
13655 | |
13656 @requirement The class satisfies the following concept requirements: | |
13657 - | |
13658 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): | |
13659 The iterator that can be moved can be moved in both directions (i.e. | |
13660 incremented and decremented). | |
13661 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): | |
13662 It is possible to write to the pointed-to element (only if @a Base is | |
13663 @ref iterator). | |
13664 | |
13665 @since version 1.0.0 | |
13666 */ | |
13667 template<typename Base> | |
13668 class json_reverse_iterator : public std::reverse_iterator<Base> | |
13669 { | |
13670 public: | |
13671 using difference_type = std::ptrdiff_t; | |
13672 /// shortcut to the reverse iterator adapter | |
13673 using base_iterator = std::reverse_iterator<Base>; | |
13674 /// the reference type for the pointed-to element | |
13675 using reference = typename Base::reference; | |
13676 | |
13677 /// create reverse iterator from iterator | |
13678 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept | |
13679 : base_iterator(it) {} | |
13680 | |
13681 /// create reverse iterator from base class | |
13682 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} | |
13683 | |
13684 /// post-increment (it++) | |
13685 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) | |
13686 { | |
13687 return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); | |
13688 } | |
13689 | |
13690 /// pre-increment (++it) | |
13691 json_reverse_iterator& operator++() | |
13692 { | |
13693 return static_cast<json_reverse_iterator&>(base_iterator::operator++()); | |
13694 } | |
13695 | |
13696 /// post-decrement (it--) | |
13697 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) | |
13698 { | |
13699 return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); | |
13700 } | |
13701 | |
13702 /// pre-decrement (--it) | |
13703 json_reverse_iterator& operator--() | |
13704 { | |
13705 return static_cast<json_reverse_iterator&>(base_iterator::operator--()); | |
13706 } | |
13707 | |
13708 /// add to iterator | |
13709 json_reverse_iterator& operator+=(difference_type i) | |
13710 { | |
13711 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); | |
13712 } | |
13713 | |
13714 /// add to iterator | |
13715 json_reverse_iterator operator+(difference_type i) const | |
13716 { | |
13717 return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); | |
13718 } | |
13719 | |
13720 /// subtract from iterator | |
13721 json_reverse_iterator operator-(difference_type i) const | |
13722 { | |
13723 return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); | |
13724 } | |
13725 | |
13726 /// return difference | |
13727 difference_type operator-(const json_reverse_iterator& other) const | |
13728 { | |
13729 return base_iterator(*this) - base_iterator(other); | |
13730 } | |
13731 | |
13732 /// access to successor | |
13733 reference operator[](difference_type n) const | |
13734 { | |
13735 return *(this->operator+(n)); | |
13736 } | |
13737 | |
13738 /// return the key of an object iterator | |
13739 auto key() const -> decltype(std::declval<Base>().key()) | |
13740 { | |
13741 auto it = --this->base(); | |
13742 return it.key(); | |
13743 } | |
13744 | |
13745 /// return the value of an iterator | |
13746 reference value() const | |
13747 { | |
13748 auto it = --this->base(); | |
13749 return it.operator * (); | |
13750 } | |
13751 }; | |
13752 | |
13753 } // namespace detail | |
13754 NLOHMANN_JSON_NAMESPACE_END | |
13755 | |
13756 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> | |
13757 | |
13758 // #include <nlohmann/detail/json_custom_base_class.hpp> | |
13759 // __ _____ _____ _____ | |
13760 // __| | __| | | | JSON for Modern C++ | |
13761 // | | |__ | | | | | | version 3.11.3 | |
13762 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
13763 // | |
13764 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
13765 // SPDX-License-Identifier: MIT | |
13766 | |
13767 | |
13768 | |
13769 #include <type_traits> // conditional, is_same | |
13770 | |
13771 // #include <nlohmann/detail/abi_macros.hpp> | |
13772 | |
13773 | |
13774 NLOHMANN_JSON_NAMESPACE_BEGIN | |
13775 namespace detail | |
13776 { | |
13777 | |
13778 /*! | |
13779 @brief Default base class of the @ref basic_json class. | |
13780 | |
13781 So that the correct implementations of the copy / move ctors / assign operators | |
13782 of @ref basic_json do not require complex case distinctions | |
13783 (no base class / custom base class used as customization point), | |
13784 @ref basic_json always has a base class. | |
13785 By default, this class is used because it is empty and thus has no effect | |
13786 on the behavior of @ref basic_json. | |
13787 */ | |
13788 struct json_default_base {}; | |
13789 | |
13790 template<class T> | |
13791 using json_base_class = typename std::conditional < | |
13792 std::is_same<T, void>::value, | |
13793 json_default_base, | |
13794 T | |
13795 >::type; | |
13796 | |
13797 } // namespace detail | |
13798 NLOHMANN_JSON_NAMESPACE_END | |
13799 | |
13800 // #include <nlohmann/detail/json_pointer.hpp> | |
13801 // __ _____ _____ _____ | |
13802 // __| | __| | | | JSON for Modern C++ | |
13803 // | | |__ | | | | | | version 3.11.3 | |
13804 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
13805 // | |
13806 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
13807 // SPDX-License-Identifier: MIT | |
13808 | |
13809 | |
13810 | |
13811 #include <algorithm> // all_of | |
13812 #include <cctype> // isdigit | |
13813 #include <cerrno> // errno, ERANGE | |
13814 #include <cstdlib> // strtoull | |
13815 #ifndef JSON_NO_IO | |
13816 #include <iosfwd> // ostream | |
13817 #endif // JSON_NO_IO | |
13818 #include <limits> // max | |
13819 #include <numeric> // accumulate | |
13820 #include <string> // string | |
13821 #include <utility> // move | |
13822 #include <vector> // vector | |
13823 | |
13824 // #include <nlohmann/detail/exceptions.hpp> | |
13825 | |
13826 // #include <nlohmann/detail/macro_scope.hpp> | |
13827 | |
13828 // #include <nlohmann/detail/string_concat.hpp> | |
13829 | |
13830 // #include <nlohmann/detail/string_escape.hpp> | |
13831 | |
13832 // #include <nlohmann/detail/value_t.hpp> | |
13833 | |
13834 | |
13835 NLOHMANN_JSON_NAMESPACE_BEGIN | |
13836 | |
13837 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document | |
13838 /// @sa https://json.nlohmann.me/api/json_pointer/ | |
13839 template<typename RefStringType> | |
13840 class json_pointer | |
13841 { | |
13842 // allow basic_json to access private members | |
13843 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
13844 friend class basic_json; | |
13845 | |
13846 template<typename> | |
13847 friend class json_pointer; | |
13848 | |
13849 template<typename T> | |
13850 struct string_t_helper | |
13851 { | |
13852 using type = T; | |
13853 }; | |
13854 | |
13855 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
13856 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> | |
13857 { | |
13858 using type = StringType; | |
13859 }; | |
13860 | |
13861 public: | |
13862 // for backwards compatibility accept BasicJsonType | |
13863 using string_t = typename string_t_helper<RefStringType>::type; | |
13864 | |
13865 /// @brief create JSON pointer | |
13866 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ | |
13867 explicit json_pointer(const string_t& s = "") | |
13868 : reference_tokens(split(s)) | |
13869 {} | |
13870 | |
13871 /// @brief return a string representation of the JSON pointer | |
13872 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ | |
13873 string_t to_string() const | |
13874 { | |
13875 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), | |
13876 string_t{}, | |
13877 [](const string_t& a, const string_t& b) | |
13878 { | |
13879 return detail::concat(a, '/', detail::escape(b)); | |
13880 }); | |
13881 } | |
13882 | |
13883 /// @brief return a string representation of the JSON pointer | |
13884 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ | |
13885 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) | |
13886 operator string_t() const | |
13887 { | |
13888 return to_string(); | |
13889 } | |
13890 | |
13891 #ifndef JSON_NO_IO | |
13892 /// @brief write string representation of the JSON pointer to stream | |
13893 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ | |
13894 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) | |
13895 { | |
13896 o << ptr.to_string(); | |
13897 return o; | |
13898 } | |
13899 #endif | |
13900 | |
13901 /// @brief append another JSON pointer at the end of this JSON pointer | |
13902 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | |
13903 json_pointer& operator/=(const json_pointer& ptr) | |
13904 { | |
13905 reference_tokens.insert(reference_tokens.end(), | |
13906 ptr.reference_tokens.begin(), | |
13907 ptr.reference_tokens.end()); | |
13908 return *this; | |
13909 } | |
13910 | |
13911 /// @brief append an unescaped reference token at the end of this JSON pointer | |
13912 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | |
13913 json_pointer& operator/=(string_t token) | |
13914 { | |
13915 push_back(std::move(token)); | |
13916 return *this; | |
13917 } | |
13918 | |
13919 /// @brief append an array index at the end of this JSON pointer | |
13920 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ | |
13921 json_pointer& operator/=(std::size_t array_idx) | |
13922 { | |
13923 return *this /= std::to_string(array_idx); | |
13924 } | |
13925 | |
13926 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer | |
13927 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | |
13928 friend json_pointer operator/(const json_pointer& lhs, | |
13929 const json_pointer& rhs) | |
13930 { | |
13931 return json_pointer(lhs) /= rhs; | |
13932 } | |
13933 | |
13934 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer | |
13935 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | |
13936 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) | |
13937 { | |
13938 return json_pointer(lhs) /= std::move(token); | |
13939 } | |
13940 | |
13941 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer | |
13942 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ | |
13943 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) | |
13944 { | |
13945 return json_pointer(lhs) /= array_idx; | |
13946 } | |
13947 | |
13948 /// @brief returns the parent of this JSON pointer | |
13949 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ | |
13950 json_pointer parent_pointer() const | |
13951 { | |
13952 if (empty()) | |
13953 { | |
13954 return *this; | |
13955 } | |
13956 | |
13957 json_pointer res = *this; | |
13958 res.pop_back(); | |
13959 return res; | |
13960 } | |
13961 | |
13962 /// @brief remove last reference token | |
13963 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ | |
13964 void pop_back() | |
13965 { | |
13966 if (JSON_HEDLEY_UNLIKELY(empty())) | |
13967 { | |
13968 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | |
13969 } | |
13970 | |
13971 reference_tokens.pop_back(); | |
13972 } | |
13973 | |
13974 /// @brief return last reference token | |
13975 /// @sa https://json.nlohmann.me/api/json_pointer/back/ | |
13976 const string_t& back() const | |
13977 { | |
13978 if (JSON_HEDLEY_UNLIKELY(empty())) | |
13979 { | |
13980 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | |
13981 } | |
13982 | |
13983 return reference_tokens.back(); | |
13984 } | |
13985 | |
13986 /// @brief append an unescaped token at the end of the reference pointer | |
13987 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ | |
13988 void push_back(const string_t& token) | |
13989 { | |
13990 reference_tokens.push_back(token); | |
13991 } | |
13992 | |
13993 /// @brief append an unescaped token at the end of the reference pointer | |
13994 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ | |
13995 void push_back(string_t&& token) | |
13996 { | |
13997 reference_tokens.push_back(std::move(token)); | |
13998 } | |
13999 | |
14000 /// @brief return whether pointer points to the root document | |
14001 /// @sa https://json.nlohmann.me/api/json_pointer/empty/ | |
14002 bool empty() const noexcept | |
14003 { | |
14004 return reference_tokens.empty(); | |
14005 } | |
14006 | |
14007 private: | |
14008 /*! | |
14009 @param[in] s reference token to be converted into an array index | |
14010 | |
14011 @return integer representation of @a s | |
14012 | |
14013 @throw parse_error.106 if an array index begins with '0' | |
14014 @throw parse_error.109 if an array index begins not with a digit | |
14015 @throw out_of_range.404 if string @a s could not be converted to an integer | |
14016 @throw out_of_range.410 if an array index exceeds size_type | |
14017 */ | |
14018 template<typename BasicJsonType> | |
14019 static typename BasicJsonType::size_type array_index(const string_t& s) | |
14020 { | |
14021 using size_type = typename BasicJsonType::size_type; | |
14022 | |
14023 // error condition (cf. RFC 6901, Sect. 4) | |
14024 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) | |
14025 { | |
14026 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); | |
14027 } | |
14028 | |
14029 // error condition (cf. RFC 6901, Sect. 4) | |
14030 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) | |
14031 { | |
14032 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); | |
14033 } | |
14034 | |
14035 const char* p = s.c_str(); | |
14036 char* p_end = nullptr; | |
14037 errno = 0; // strtoull doesn't reset errno | |
14038 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) | |
14039 if (p == p_end // invalid input or empty string | |
14040 || errno == ERANGE // out of range | |
14041 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read | |
14042 { | |
14043 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); | |
14044 } | |
14045 | |
14046 // only triggered on special platforms (like 32bit), see also | |
14047 // https://github.com/nlohmann/json/pull/2203 | |
14048 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int) | |
14049 { | |
14050 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE | |
14051 } | |
14052 | |
14053 return static_cast<size_type>(res); | |
14054 } | |
14055 | |
14056 JSON_PRIVATE_UNLESS_TESTED: | |
14057 json_pointer top() const | |
14058 { | |
14059 if (JSON_HEDLEY_UNLIKELY(empty())) | |
14060 { | |
14061 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); | |
14062 } | |
14063 | |
14064 json_pointer result = *this; | |
14065 result.reference_tokens = {reference_tokens[0]}; | |
14066 return result; | |
14067 } | |
14068 | |
14069 private: | |
14070 /*! | |
14071 @brief create and return a reference to the pointed to value | |
14072 | |
14073 @complexity Linear in the number of reference tokens. | |
14074 | |
14075 @throw parse_error.109 if array index is not a number | |
14076 @throw type_error.313 if value cannot be unflattened | |
14077 */ | |
14078 template<typename BasicJsonType> | |
14079 BasicJsonType& get_and_create(BasicJsonType& j) const | |
14080 { | |
14081 auto* result = &j; | |
14082 | |
14083 // in case no reference tokens exist, return a reference to the JSON value | |
14084 // j which will be overwritten by a primitive value | |
14085 for (const auto& reference_token : reference_tokens) | |
14086 { | |
14087 switch (result->type()) | |
14088 { | |
14089 case detail::value_t::null: | |
14090 { | |
14091 if (reference_token == "0") | |
14092 { | |
14093 // start a new array if reference token is 0 | |
14094 result = &result->operator[](0); | |
14095 } | |
14096 else | |
14097 { | |
14098 // start a new object otherwise | |
14099 result = &result->operator[](reference_token); | |
14100 } | |
14101 break; | |
14102 } | |
14103 | |
14104 case detail::value_t::object: | |
14105 { | |
14106 // create an entry in the object | |
14107 result = &result->operator[](reference_token); | |
14108 break; | |
14109 } | |
14110 | |
14111 case detail::value_t::array: | |
14112 { | |
14113 // create an entry in the array | |
14114 result = &result->operator[](array_index<BasicJsonType>(reference_token)); | |
14115 break; | |
14116 } | |
14117 | |
14118 /* | |
14119 The following code is only reached if there exists a reference | |
14120 token _and_ the current value is primitive. In this case, we have | |
14121 an error situation, because primitive values may only occur as | |
14122 single value; that is, with an empty list of reference tokens. | |
14123 */ | |
14124 case detail::value_t::string: | |
14125 case detail::value_t::boolean: | |
14126 case detail::value_t::number_integer: | |
14127 case detail::value_t::number_unsigned: | |
14128 case detail::value_t::number_float: | |
14129 case detail::value_t::binary: | |
14130 case detail::value_t::discarded: | |
14131 default: | |
14132 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); | |
14133 } | |
14134 } | |
14135 | |
14136 return *result; | |
14137 } | |
14138 | |
14139 /*! | |
14140 @brief return a reference to the pointed to value | |
14141 | |
14142 @note This version does not throw if a value is not present, but tries to | |
14143 create nested values instead. For instance, calling this function | |
14144 with pointer `"/this/that"` on a null value is equivalent to calling | |
14145 `operator[]("this").operator[]("that")` on that value, effectively | |
14146 changing the null value to an object. | |
14147 | |
14148 @param[in] ptr a JSON value | |
14149 | |
14150 @return reference to the JSON value pointed to by the JSON pointer | |
14151 | |
14152 @complexity Linear in the length of the JSON pointer. | |
14153 | |
14154 @throw parse_error.106 if an array index begins with '0' | |
14155 @throw parse_error.109 if an array index was not a number | |
14156 @throw out_of_range.404 if the JSON pointer can not be resolved | |
14157 */ | |
14158 template<typename BasicJsonType> | |
14159 BasicJsonType& get_unchecked(BasicJsonType* ptr) const | |
14160 { | |
14161 for (const auto& reference_token : reference_tokens) | |
14162 { | |
14163 // convert null values to arrays or objects before continuing | |
14164 if (ptr->is_null()) | |
14165 { | |
14166 // check if reference token is a number | |
14167 const bool nums = | |
14168 std::all_of(reference_token.begin(), reference_token.end(), | |
14169 [](const unsigned char x) | |
14170 { | |
14171 return std::isdigit(x); | |
14172 }); | |
14173 | |
14174 // change value to array for numbers or "-" or to object otherwise | |
14175 *ptr = (nums || reference_token == "-") | |
14176 ? detail::value_t::array | |
14177 : detail::value_t::object; | |
14178 } | |
14179 | |
14180 switch (ptr->type()) | |
14181 { | |
14182 case detail::value_t::object: | |
14183 { | |
14184 // use unchecked object access | |
14185 ptr = &ptr->operator[](reference_token); | |
14186 break; | |
14187 } | |
14188 | |
14189 case detail::value_t::array: | |
14190 { | |
14191 if (reference_token == "-") | |
14192 { | |
14193 // explicitly treat "-" as index beyond the end | |
14194 ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); | |
14195 } | |
14196 else | |
14197 { | |
14198 // convert array index to number; unchecked access | |
14199 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); | |
14200 } | |
14201 break; | |
14202 } | |
14203 | |
14204 case detail::value_t::null: | |
14205 case detail::value_t::string: | |
14206 case detail::value_t::boolean: | |
14207 case detail::value_t::number_integer: | |
14208 case detail::value_t::number_unsigned: | |
14209 case detail::value_t::number_float: | |
14210 case detail::value_t::binary: | |
14211 case detail::value_t::discarded: | |
14212 default: | |
14213 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | |
14214 } | |
14215 } | |
14216 | |
14217 return *ptr; | |
14218 } | |
14219 | |
14220 /*! | |
14221 @throw parse_error.106 if an array index begins with '0' | |
14222 @throw parse_error.109 if an array index was not a number | |
14223 @throw out_of_range.402 if the array index '-' is used | |
14224 @throw out_of_range.404 if the JSON pointer can not be resolved | |
14225 */ | |
14226 template<typename BasicJsonType> | |
14227 BasicJsonType& get_checked(BasicJsonType* ptr) const | |
14228 { | |
14229 for (const auto& reference_token : reference_tokens) | |
14230 { | |
14231 switch (ptr->type()) | |
14232 { | |
14233 case detail::value_t::object: | |
14234 { | |
14235 // note: at performs range check | |
14236 ptr = &ptr->at(reference_token); | |
14237 break; | |
14238 } | |
14239 | |
14240 case detail::value_t::array: | |
14241 { | |
14242 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | |
14243 { | |
14244 // "-" always fails the range check | |
14245 JSON_THROW(detail::out_of_range::create(402, detail::concat( | |
14246 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), | |
14247 ") is out of range"), ptr)); | |
14248 } | |
14249 | |
14250 // note: at performs range check | |
14251 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); | |
14252 break; | |
14253 } | |
14254 | |
14255 case detail::value_t::null: | |
14256 case detail::value_t::string: | |
14257 case detail::value_t::boolean: | |
14258 case detail::value_t::number_integer: | |
14259 case detail::value_t::number_unsigned: | |
14260 case detail::value_t::number_float: | |
14261 case detail::value_t::binary: | |
14262 case detail::value_t::discarded: | |
14263 default: | |
14264 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | |
14265 } | |
14266 } | |
14267 | |
14268 return *ptr; | |
14269 } | |
14270 | |
14271 /*! | |
14272 @brief return a const reference to the pointed to value | |
14273 | |
14274 @param[in] ptr a JSON value | |
14275 | |
14276 @return const reference to the JSON value pointed to by the JSON | |
14277 pointer | |
14278 | |
14279 @throw parse_error.106 if an array index begins with '0' | |
14280 @throw parse_error.109 if an array index was not a number | |
14281 @throw out_of_range.402 if the array index '-' is used | |
14282 @throw out_of_range.404 if the JSON pointer can not be resolved | |
14283 */ | |
14284 template<typename BasicJsonType> | |
14285 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const | |
14286 { | |
14287 for (const auto& reference_token : reference_tokens) | |
14288 { | |
14289 switch (ptr->type()) | |
14290 { | |
14291 case detail::value_t::object: | |
14292 { | |
14293 // use unchecked object access | |
14294 ptr = &ptr->operator[](reference_token); | |
14295 break; | |
14296 } | |
14297 | |
14298 case detail::value_t::array: | |
14299 { | |
14300 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | |
14301 { | |
14302 // "-" cannot be used for const access | |
14303 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); | |
14304 } | |
14305 | |
14306 // use unchecked array access | |
14307 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); | |
14308 break; | |
14309 } | |
14310 | |
14311 case detail::value_t::null: | |
14312 case detail::value_t::string: | |
14313 case detail::value_t::boolean: | |
14314 case detail::value_t::number_integer: | |
14315 case detail::value_t::number_unsigned: | |
14316 case detail::value_t::number_float: | |
14317 case detail::value_t::binary: | |
14318 case detail::value_t::discarded: | |
14319 default: | |
14320 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | |
14321 } | |
14322 } | |
14323 | |
14324 return *ptr; | |
14325 } | |
14326 | |
14327 /*! | |
14328 @throw parse_error.106 if an array index begins with '0' | |
14329 @throw parse_error.109 if an array index was not a number | |
14330 @throw out_of_range.402 if the array index '-' is used | |
14331 @throw out_of_range.404 if the JSON pointer can not be resolved | |
14332 */ | |
14333 template<typename BasicJsonType> | |
14334 const BasicJsonType& get_checked(const BasicJsonType* ptr) const | |
14335 { | |
14336 for (const auto& reference_token : reference_tokens) | |
14337 { | |
14338 switch (ptr->type()) | |
14339 { | |
14340 case detail::value_t::object: | |
14341 { | |
14342 // note: at performs range check | |
14343 ptr = &ptr->at(reference_token); | |
14344 break; | |
14345 } | |
14346 | |
14347 case detail::value_t::array: | |
14348 { | |
14349 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | |
14350 { | |
14351 // "-" always fails the range check | |
14352 JSON_THROW(detail::out_of_range::create(402, detail::concat( | |
14353 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), | |
14354 ") is out of range"), ptr)); | |
14355 } | |
14356 | |
14357 // note: at performs range check | |
14358 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); | |
14359 break; | |
14360 } | |
14361 | |
14362 case detail::value_t::null: | |
14363 case detail::value_t::string: | |
14364 case detail::value_t::boolean: | |
14365 case detail::value_t::number_integer: | |
14366 case detail::value_t::number_unsigned: | |
14367 case detail::value_t::number_float: | |
14368 case detail::value_t::binary: | |
14369 case detail::value_t::discarded: | |
14370 default: | |
14371 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); | |
14372 } | |
14373 } | |
14374 | |
14375 return *ptr; | |
14376 } | |
14377 | |
14378 /*! | |
14379 @throw parse_error.106 if an array index begins with '0' | |
14380 @throw parse_error.109 if an array index was not a number | |
14381 */ | |
14382 template<typename BasicJsonType> | |
14383 bool contains(const BasicJsonType* ptr) const | |
14384 { | |
14385 for (const auto& reference_token : reference_tokens) | |
14386 { | |
14387 switch (ptr->type()) | |
14388 { | |
14389 case detail::value_t::object: | |
14390 { | |
14391 if (!ptr->contains(reference_token)) | |
14392 { | |
14393 // we did not find the key in the object | |
14394 return false; | |
14395 } | |
14396 | |
14397 ptr = &ptr->operator[](reference_token); | |
14398 break; | |
14399 } | |
14400 | |
14401 case detail::value_t::array: | |
14402 { | |
14403 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) | |
14404 { | |
14405 // "-" always fails the range check | |
14406 return false; | |
14407 } | |
14408 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) | |
14409 { | |
14410 // invalid char | |
14411 return false; | |
14412 } | |
14413 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) | |
14414 { | |
14415 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) | |
14416 { | |
14417 // first char should be between '1' and '9' | |
14418 return false; | |
14419 } | |
14420 for (std::size_t i = 1; i < reference_token.size(); i++) | |
14421 { | |
14422 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) | |
14423 { | |
14424 // other char should be between '0' and '9' | |
14425 return false; | |
14426 } | |
14427 } | |
14428 } | |
14429 | |
14430 const auto idx = array_index<BasicJsonType>(reference_token); | |
14431 if (idx >= ptr->size()) | |
14432 { | |
14433 // index out of range | |
14434 return false; | |
14435 } | |
14436 | |
14437 ptr = &ptr->operator[](idx); | |
14438 break; | |
14439 } | |
14440 | |
14441 case detail::value_t::null: | |
14442 case detail::value_t::string: | |
14443 case detail::value_t::boolean: | |
14444 case detail::value_t::number_integer: | |
14445 case detail::value_t::number_unsigned: | |
14446 case detail::value_t::number_float: | |
14447 case detail::value_t::binary: | |
14448 case detail::value_t::discarded: | |
14449 default: | |
14450 { | |
14451 // we do not expect primitive values if there is still a | |
14452 // reference token to process | |
14453 return false; | |
14454 } | |
14455 } | |
14456 } | |
14457 | |
14458 // no reference token left means we found a primitive value | |
14459 return true; | |
14460 } | |
14461 | |
14462 /*! | |
14463 @brief split the string input to reference tokens | |
14464 | |
14465 @note This function is only called by the json_pointer constructor. | |
14466 All exceptions below are documented there. | |
14467 | |
14468 @throw parse_error.107 if the pointer is not empty or begins with '/' | |
14469 @throw parse_error.108 if character '~' is not followed by '0' or '1' | |
14470 */ | |
14471 static std::vector<string_t> split(const string_t& reference_string) | |
14472 { | |
14473 std::vector<string_t> result; | |
14474 | |
14475 // special case: empty reference string -> no reference tokens | |
14476 if (reference_string.empty()) | |
14477 { | |
14478 return result; | |
14479 } | |
14480 | |
14481 // check if nonempty reference string begins with slash | |
14482 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) | |
14483 { | |
14484 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); | |
14485 } | |
14486 | |
14487 // extract the reference tokens: | |
14488 // - slash: position of the last read slash (or end of string) | |
14489 // - start: position after the previous slash | |
14490 for ( | |
14491 // search for the first slash after the first character | |
14492 std::size_t slash = reference_string.find_first_of('/', 1), | |
14493 // set the beginning of the first reference token | |
14494 start = 1; | |
14495 // we can stop if start == 0 (if slash == string_t::npos) | |
14496 start != 0; | |
14497 // set the beginning of the next reference token | |
14498 // (will eventually be 0 if slash == string_t::npos) | |
14499 start = (slash == string_t::npos) ? 0 : slash + 1, | |
14500 // find next slash | |
14501 slash = reference_string.find_first_of('/', start)) | |
14502 { | |
14503 // use the text between the beginning of the reference token | |
14504 // (start) and the last slash (slash). | |
14505 auto reference_token = reference_string.substr(start, slash - start); | |
14506 | |
14507 // check reference tokens are properly escaped | |
14508 for (std::size_t pos = reference_token.find_first_of('~'); | |
14509 pos != string_t::npos; | |
14510 pos = reference_token.find_first_of('~', pos + 1)) | |
14511 { | |
14512 JSON_ASSERT(reference_token[pos] == '~'); | |
14513 | |
14514 // ~ must be followed by 0 or 1 | |
14515 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || | |
14516 (reference_token[pos + 1] != '0' && | |
14517 reference_token[pos + 1] != '1'))) | |
14518 { | |
14519 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); | |
14520 } | |
14521 } | |
14522 | |
14523 // finally, store the reference token | |
14524 detail::unescape(reference_token); | |
14525 result.push_back(reference_token); | |
14526 } | |
14527 | |
14528 return result; | |
14529 } | |
14530 | |
14531 private: | |
14532 /*! | |
14533 @param[in] reference_string the reference string to the current value | |
14534 @param[in] value the value to consider | |
14535 @param[in,out] result the result object to insert values to | |
14536 | |
14537 @note Empty objects or arrays are flattened to `null`. | |
14538 */ | |
14539 template<typename BasicJsonType> | |
14540 static void flatten(const string_t& reference_string, | |
14541 const BasicJsonType& value, | |
14542 BasicJsonType& result) | |
14543 { | |
14544 switch (value.type()) | |
14545 { | |
14546 case detail::value_t::array: | |
14547 { | |
14548 if (value.m_data.m_value.array->empty()) | |
14549 { | |
14550 // flatten empty array as null | |
14551 result[reference_string] = nullptr; | |
14552 } | |
14553 else | |
14554 { | |
14555 // iterate array and use index as reference string | |
14556 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) | |
14557 { | |
14558 flatten(detail::concat(reference_string, '/', std::to_string(i)), | |
14559 value.m_data.m_value.array->operator[](i), result); | |
14560 } | |
14561 } | |
14562 break; | |
14563 } | |
14564 | |
14565 case detail::value_t::object: | |
14566 { | |
14567 if (value.m_data.m_value.object->empty()) | |
14568 { | |
14569 // flatten empty object as null | |
14570 result[reference_string] = nullptr; | |
14571 } | |
14572 else | |
14573 { | |
14574 // iterate object and use keys as reference string | |
14575 for (const auto& element : *value.m_data.m_value.object) | |
14576 { | |
14577 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); | |
14578 } | |
14579 } | |
14580 break; | |
14581 } | |
14582 | |
14583 case detail::value_t::null: | |
14584 case detail::value_t::string: | |
14585 case detail::value_t::boolean: | |
14586 case detail::value_t::number_integer: | |
14587 case detail::value_t::number_unsigned: | |
14588 case detail::value_t::number_float: | |
14589 case detail::value_t::binary: | |
14590 case detail::value_t::discarded: | |
14591 default: | |
14592 { | |
14593 // add primitive value with its reference string | |
14594 result[reference_string] = value; | |
14595 break; | |
14596 } | |
14597 } | |
14598 } | |
14599 | |
14600 /*! | |
14601 @param[in] value flattened JSON | |
14602 | |
14603 @return unflattened JSON | |
14604 | |
14605 @throw parse_error.109 if array index is not a number | |
14606 @throw type_error.314 if value is not an object | |
14607 @throw type_error.315 if object values are not primitive | |
14608 @throw type_error.313 if value cannot be unflattened | |
14609 */ | |
14610 template<typename BasicJsonType> | |
14611 static BasicJsonType | |
14612 unflatten(const BasicJsonType& value) | |
14613 { | |
14614 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) | |
14615 { | |
14616 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); | |
14617 } | |
14618 | |
14619 BasicJsonType result; | |
14620 | |
14621 // iterate the JSON object values | |
14622 for (const auto& element : *value.m_data.m_value.object) | |
14623 { | |
14624 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) | |
14625 { | |
14626 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); | |
14627 } | |
14628 | |
14629 // assign value to reference pointed to by JSON pointer; Note that if | |
14630 // the JSON pointer is "" (i.e., points to the whole value), function | |
14631 // get_and_create returns a reference to result itself. An assignment | |
14632 // will then create a primitive value. | |
14633 json_pointer(element.first).get_and_create(result) = element.second; | |
14634 } | |
14635 | |
14636 return result; | |
14637 } | |
14638 | |
14639 // can't use conversion operator because of ambiguity | |
14640 json_pointer<string_t> convert() const& | |
14641 { | |
14642 json_pointer<string_t> result; | |
14643 result.reference_tokens = reference_tokens; | |
14644 return result; | |
14645 } | |
14646 | |
14647 json_pointer<string_t> convert()&& | |
14648 { | |
14649 json_pointer<string_t> result; | |
14650 result.reference_tokens = std::move(reference_tokens); | |
14651 return result; | |
14652 } | |
14653 | |
14654 public: | |
14655 #if JSON_HAS_THREE_WAY_COMPARISON | |
14656 /// @brief compares two JSON pointers for equality | |
14657 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | |
14658 template<typename RefStringTypeRhs> | |
14659 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept | |
14660 { | |
14661 return reference_tokens == rhs.reference_tokens; | |
14662 } | |
14663 | |
14664 /// @brief compares JSON pointer and string for equality | |
14665 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | |
14666 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) | |
14667 bool operator==(const string_t& rhs) const | |
14668 { | |
14669 return *this == json_pointer(rhs); | |
14670 } | |
14671 | |
14672 /// @brief 3-way compares two JSON pointers | |
14673 template<typename RefStringTypeRhs> | |
14674 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD* | |
14675 { | |
14676 return reference_tokens <=> rhs.reference_tokens; // *NOPAD* | |
14677 } | |
14678 #else | |
14679 /// @brief compares two JSON pointers for equality | |
14680 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | |
14681 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14682 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14683 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | |
14684 const json_pointer<RefStringTypeRhs>& rhs) noexcept; | |
14685 | |
14686 /// @brief compares JSON pointer and string for equality | |
14687 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | |
14688 template<typename RefStringTypeLhs, typename StringType> | |
14689 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14690 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | |
14691 const StringType& rhs); | |
14692 | |
14693 /// @brief compares string and JSON pointer for equality | |
14694 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ | |
14695 template<typename RefStringTypeRhs, typename StringType> | |
14696 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14697 friend bool operator==(const StringType& lhs, | |
14698 const json_pointer<RefStringTypeRhs>& rhs); | |
14699 | |
14700 /// @brief compares two JSON pointers for inequality | |
14701 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | |
14702 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14703 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14704 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | |
14705 const json_pointer<RefStringTypeRhs>& rhs) noexcept; | |
14706 | |
14707 /// @brief compares JSON pointer and string for inequality | |
14708 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | |
14709 template<typename RefStringTypeLhs, typename StringType> | |
14710 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14711 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | |
14712 const StringType& rhs); | |
14713 | |
14714 /// @brief compares string and JSON pointer for inequality | |
14715 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ | |
14716 template<typename RefStringTypeRhs, typename StringType> | |
14717 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14718 friend bool operator!=(const StringType& lhs, | |
14719 const json_pointer<RefStringTypeRhs>& rhs); | |
14720 | |
14721 /// @brief compares two JSON pointer for less-than | |
14722 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14723 // NOLINTNEXTLINE(readability-redundant-declaration) | |
14724 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, | |
14725 const json_pointer<RefStringTypeRhs>& rhs) noexcept; | |
14726 #endif | |
14727 | |
14728 private: | |
14729 /// the reference tokens | |
14730 std::vector<string_t> reference_tokens; | |
14731 }; | |
14732 | |
14733 #if !JSON_HAS_THREE_WAY_COMPARISON | |
14734 // functions cannot be defined inside class due to ODR violations | |
14735 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14736 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | |
14737 const json_pointer<RefStringTypeRhs>& rhs) noexcept | |
14738 { | |
14739 return lhs.reference_tokens == rhs.reference_tokens; | |
14740 } | |
14741 | |
14742 template<typename RefStringTypeLhs, | |
14743 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> | |
14744 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) | |
14745 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, | |
14746 const StringType& rhs) | |
14747 { | |
14748 return lhs == json_pointer<RefStringTypeLhs>(rhs); | |
14749 } | |
14750 | |
14751 template<typename RefStringTypeRhs, | |
14752 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> | |
14753 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) | |
14754 inline bool operator==(const StringType& lhs, | |
14755 const json_pointer<RefStringTypeRhs>& rhs) | |
14756 { | |
14757 return json_pointer<RefStringTypeRhs>(lhs) == rhs; | |
14758 } | |
14759 | |
14760 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14761 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | |
14762 const json_pointer<RefStringTypeRhs>& rhs) noexcept | |
14763 { | |
14764 return !(lhs == rhs); | |
14765 } | |
14766 | |
14767 template<typename RefStringTypeLhs, | |
14768 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> | |
14769 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) | |
14770 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, | |
14771 const StringType& rhs) | |
14772 { | |
14773 return !(lhs == rhs); | |
14774 } | |
14775 | |
14776 template<typename RefStringTypeRhs, | |
14777 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> | |
14778 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) | |
14779 inline bool operator!=(const StringType& lhs, | |
14780 const json_pointer<RefStringTypeRhs>& rhs) | |
14781 { | |
14782 return !(lhs == rhs); | |
14783 } | |
14784 | |
14785 template<typename RefStringTypeLhs, typename RefStringTypeRhs> | |
14786 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, | |
14787 const json_pointer<RefStringTypeRhs>& rhs) noexcept | |
14788 { | |
14789 return lhs.reference_tokens < rhs.reference_tokens; | |
14790 } | |
14791 #endif | |
14792 | |
14793 NLOHMANN_JSON_NAMESPACE_END | |
14794 | |
14795 // #include <nlohmann/detail/json_ref.hpp> | |
14796 // __ _____ _____ _____ | |
14797 // __| | __| | | | JSON for Modern C++ | |
14798 // | | |__ | | | | | | version 3.11.3 | |
14799 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
14800 // | |
14801 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
14802 // SPDX-License-Identifier: MIT | |
14803 | |
14804 | |
14805 | |
14806 #include <initializer_list> | |
14807 #include <utility> | |
14808 | |
14809 // #include <nlohmann/detail/abi_macros.hpp> | |
14810 | |
14811 // #include <nlohmann/detail/meta/type_traits.hpp> | |
14812 | |
14813 | |
14814 NLOHMANN_JSON_NAMESPACE_BEGIN | |
14815 namespace detail | |
14816 { | |
14817 | |
14818 template<typename BasicJsonType> | |
14819 class json_ref | |
14820 { | |
14821 public: | |
14822 using value_type = BasicJsonType; | |
14823 | |
14824 json_ref(value_type&& value) | |
14825 : owned_value(std::move(value)) | |
14826 {} | |
14827 | |
14828 json_ref(const value_type& value) | |
14829 : value_ref(&value) | |
14830 {} | |
14831 | |
14832 json_ref(std::initializer_list<json_ref> init) | |
14833 : owned_value(init) | |
14834 {} | |
14835 | |
14836 template < | |
14837 class... Args, | |
14838 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 > | |
14839 json_ref(Args && ... args) | |
14840 : owned_value(std::forward<Args>(args)...) | |
14841 {} | |
14842 | |
14843 // class should be movable only | |
14844 json_ref(json_ref&&) noexcept = default; | |
14845 json_ref(const json_ref&) = delete; | |
14846 json_ref& operator=(const json_ref&) = delete; | |
14847 json_ref& operator=(json_ref&&) = delete; | |
14848 ~json_ref() = default; | |
14849 | |
14850 value_type moved_or_copied() const | |
14851 { | |
14852 if (value_ref == nullptr) | |
14853 { | |
14854 return std::move(owned_value); | |
14855 } | |
14856 return *value_ref; | |
14857 } | |
14858 | |
14859 value_type const& operator*() const | |
14860 { | |
14861 return value_ref ? *value_ref : owned_value; | |
14862 } | |
14863 | |
14864 value_type const* operator->() const | |
14865 { | |
14866 return &** this; | |
14867 } | |
14868 | |
14869 private: | |
14870 mutable value_type owned_value = nullptr; | |
14871 value_type const* value_ref = nullptr; | |
14872 }; | |
14873 | |
14874 } // namespace detail | |
14875 NLOHMANN_JSON_NAMESPACE_END | |
14876 | |
14877 // #include <nlohmann/detail/macro_scope.hpp> | |
14878 | |
14879 // #include <nlohmann/detail/string_concat.hpp> | |
14880 | |
14881 // #include <nlohmann/detail/string_escape.hpp> | |
14882 | |
14883 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
14884 | |
14885 // #include <nlohmann/detail/meta/type_traits.hpp> | |
14886 | |
14887 // #include <nlohmann/detail/output/binary_writer.hpp> | |
14888 // __ _____ _____ _____ | |
14889 // __| | __| | | | JSON for Modern C++ | |
14890 // | | |__ | | | | | | version 3.11.3 | |
14891 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
14892 // | |
14893 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
14894 // SPDX-License-Identifier: MIT | |
14895 | |
14896 | |
14897 | |
14898 #include <algorithm> // reverse | |
14899 #include <array> // array | |
14900 #include <map> // map | |
14901 #include <cmath> // isnan, isinf | |
14902 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t | |
14903 #include <cstring> // memcpy | |
14904 #include <limits> // numeric_limits | |
14905 #include <string> // string | |
14906 #include <utility> // move | |
14907 #include <vector> // vector | |
14908 | |
14909 // #include <nlohmann/detail/input/binary_reader.hpp> | |
14910 | |
14911 // #include <nlohmann/detail/macro_scope.hpp> | |
14912 | |
14913 // #include <nlohmann/detail/output/output_adapters.hpp> | |
14914 // __ _____ _____ _____ | |
14915 // __| | __| | | | JSON for Modern C++ | |
14916 // | | |__ | | | | | | version 3.11.3 | |
14917 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
14918 // | |
14919 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
14920 // SPDX-License-Identifier: MIT | |
14921 | |
14922 | |
14923 | |
14924 #include <algorithm> // copy | |
14925 #include <cstddef> // size_t | |
14926 #include <iterator> // back_inserter | |
14927 #include <memory> // shared_ptr, make_shared | |
14928 #include <string> // basic_string | |
14929 #include <vector> // vector | |
14930 | |
14931 #ifndef JSON_NO_IO | |
14932 #include <ios> // streamsize | |
14933 #include <ostream> // basic_ostream | |
14934 #endif // JSON_NO_IO | |
14935 | |
14936 // #include <nlohmann/detail/macro_scope.hpp> | |
14937 | |
14938 | |
14939 NLOHMANN_JSON_NAMESPACE_BEGIN | |
14940 namespace detail | |
14941 { | |
14942 | |
14943 /// abstract output adapter interface | |
14944 template<typename CharType> struct output_adapter_protocol | |
14945 { | |
14946 virtual void write_character(CharType c) = 0; | |
14947 virtual void write_characters(const CharType* s, std::size_t length) = 0; | |
14948 virtual ~output_adapter_protocol() = default; | |
14949 | |
14950 output_adapter_protocol() = default; | |
14951 output_adapter_protocol(const output_adapter_protocol&) = default; | |
14952 output_adapter_protocol(output_adapter_protocol&&) noexcept = default; | |
14953 output_adapter_protocol& operator=(const output_adapter_protocol&) = default; | |
14954 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; | |
14955 }; | |
14956 | |
14957 /// a type to simplify interfaces | |
14958 template<typename CharType> | |
14959 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; | |
14960 | |
14961 /// output adapter for byte vectors | |
14962 template<typename CharType, typename AllocatorType = std::allocator<CharType>> | |
14963 class output_vector_adapter : public output_adapter_protocol<CharType> | |
14964 { | |
14965 public: | |
14966 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept | |
14967 : v(vec) | |
14968 {} | |
14969 | |
14970 void write_character(CharType c) override | |
14971 { | |
14972 v.push_back(c); | |
14973 } | |
14974 | |
14975 JSON_HEDLEY_NON_NULL(2) | |
14976 void write_characters(const CharType* s, std::size_t length) override | |
14977 { | |
14978 v.insert(v.end(), s, s + length); | |
14979 } | |
14980 | |
14981 private: | |
14982 std::vector<CharType, AllocatorType>& v; | |
14983 }; | |
14984 | |
14985 #ifndef JSON_NO_IO | |
14986 /// output adapter for output streams | |
14987 template<typename CharType> | |
14988 class output_stream_adapter : public output_adapter_protocol<CharType> | |
14989 { | |
14990 public: | |
14991 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept | |
14992 : stream(s) | |
14993 {} | |
14994 | |
14995 void write_character(CharType c) override | |
14996 { | |
14997 stream.put(c); | |
14998 } | |
14999 | |
15000 JSON_HEDLEY_NON_NULL(2) | |
15001 void write_characters(const CharType* s, std::size_t length) override | |
15002 { | |
15003 stream.write(s, static_cast<std::streamsize>(length)); | |
15004 } | |
15005 | |
15006 private: | |
15007 std::basic_ostream<CharType>& stream; | |
15008 }; | |
15009 #endif // JSON_NO_IO | |
15010 | |
15011 /// output adapter for basic_string | |
15012 template<typename CharType, typename StringType = std::basic_string<CharType>> | |
15013 class output_string_adapter : public output_adapter_protocol<CharType> | |
15014 { | |
15015 public: | |
15016 explicit output_string_adapter(StringType& s) noexcept | |
15017 : str(s) | |
15018 {} | |
15019 | |
15020 void write_character(CharType c) override | |
15021 { | |
15022 str.push_back(c); | |
15023 } | |
15024 | |
15025 JSON_HEDLEY_NON_NULL(2) | |
15026 void write_characters(const CharType* s, std::size_t length) override | |
15027 { | |
15028 str.append(s, length); | |
15029 } | |
15030 | |
15031 private: | |
15032 StringType& str; | |
15033 }; | |
15034 | |
15035 template<typename CharType, typename StringType = std::basic_string<CharType>> | |
15036 class output_adapter | |
15037 { | |
15038 public: | |
15039 template<typename AllocatorType = std::allocator<CharType>> | |
15040 output_adapter(std::vector<CharType, AllocatorType>& vec) | |
15041 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {} | |
15042 | |
15043 #ifndef JSON_NO_IO | |
15044 output_adapter(std::basic_ostream<CharType>& s) | |
15045 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} | |
15046 #endif // JSON_NO_IO | |
15047 | |
15048 output_adapter(StringType& s) | |
15049 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} | |
15050 | |
15051 operator output_adapter_t<CharType>() | |
15052 { | |
15053 return oa; | |
15054 } | |
15055 | |
15056 private: | |
15057 output_adapter_t<CharType> oa = nullptr; | |
15058 }; | |
15059 | |
15060 } // namespace detail | |
15061 NLOHMANN_JSON_NAMESPACE_END | |
15062 | |
15063 // #include <nlohmann/detail/string_concat.hpp> | |
15064 | |
15065 | |
15066 NLOHMANN_JSON_NAMESPACE_BEGIN | |
15067 namespace detail | |
15068 { | |
15069 | |
15070 /////////////////// | |
15071 // binary writer // | |
15072 /////////////////// | |
15073 | |
15074 /*! | |
15075 @brief serialization to CBOR and MessagePack values | |
15076 */ | |
15077 template<typename BasicJsonType, typename CharType> | |
15078 class binary_writer | |
15079 { | |
15080 using string_t = typename BasicJsonType::string_t; | |
15081 using binary_t = typename BasicJsonType::binary_t; | |
15082 using number_float_t = typename BasicJsonType::number_float_t; | |
15083 | |
15084 public: | |
15085 /*! | |
15086 @brief create a binary writer | |
15087 | |
15088 @param[in] adapter output adapter to write to | |
15089 */ | |
15090 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) | |
15091 { | |
15092 JSON_ASSERT(oa); | |
15093 } | |
15094 | |
15095 /*! | |
15096 @param[in] j JSON value to serialize | |
15097 @pre j.type() == value_t::object | |
15098 */ | |
15099 void write_bson(const BasicJsonType& j) | |
15100 { | |
15101 switch (j.type()) | |
15102 { | |
15103 case value_t::object: | |
15104 { | |
15105 write_bson_object(*j.m_data.m_value.object); | |
15106 break; | |
15107 } | |
15108 | |
15109 case value_t::null: | |
15110 case value_t::array: | |
15111 case value_t::string: | |
15112 case value_t::boolean: | |
15113 case value_t::number_integer: | |
15114 case value_t::number_unsigned: | |
15115 case value_t::number_float: | |
15116 case value_t::binary: | |
15117 case value_t::discarded: | |
15118 default: | |
15119 { | |
15120 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j)); | |
15121 } | |
15122 } | |
15123 } | |
15124 | |
15125 /*! | |
15126 @param[in] j JSON value to serialize | |
15127 */ | |
15128 void write_cbor(const BasicJsonType& j) | |
15129 { | |
15130 switch (j.type()) | |
15131 { | |
15132 case value_t::null: | |
15133 { | |
15134 oa->write_character(to_char_type(0xF6)); | |
15135 break; | |
15136 } | |
15137 | |
15138 case value_t::boolean: | |
15139 { | |
15140 oa->write_character(j.m_data.m_value.boolean | |
15141 ? to_char_type(0xF5) | |
15142 : to_char_type(0xF4)); | |
15143 break; | |
15144 } | |
15145 | |
15146 case value_t::number_integer: | |
15147 { | |
15148 if (j.m_data.m_value.number_integer >= 0) | |
15149 { | |
15150 // CBOR does not differentiate between positive signed | |
15151 // integers and unsigned integers. Therefore, we used the | |
15152 // code from the value_t::number_unsigned case here. | |
15153 if (j.m_data.m_value.number_integer <= 0x17) | |
15154 { | |
15155 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15156 } | |
15157 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) | |
15158 { | |
15159 oa->write_character(to_char_type(0x18)); | |
15160 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15161 } | |
15162 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) | |
15163 { | |
15164 oa->write_character(to_char_type(0x19)); | |
15165 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); | |
15166 } | |
15167 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) | |
15168 { | |
15169 oa->write_character(to_char_type(0x1A)); | |
15170 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); | |
15171 } | |
15172 else | |
15173 { | |
15174 oa->write_character(to_char_type(0x1B)); | |
15175 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); | |
15176 } | |
15177 } | |
15178 else | |
15179 { | |
15180 // The conversions below encode the sign in the first | |
15181 // byte, and the value is converted to a positive number. | |
15182 const auto positive_number = -1 - j.m_data.m_value.number_integer; | |
15183 if (j.m_data.m_value.number_integer >= -24) | |
15184 { | |
15185 write_number(static_cast<std::uint8_t>(0x20 + positive_number)); | |
15186 } | |
15187 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) | |
15188 { | |
15189 oa->write_character(to_char_type(0x38)); | |
15190 write_number(static_cast<std::uint8_t>(positive_number)); | |
15191 } | |
15192 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) | |
15193 { | |
15194 oa->write_character(to_char_type(0x39)); | |
15195 write_number(static_cast<std::uint16_t>(positive_number)); | |
15196 } | |
15197 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) | |
15198 { | |
15199 oa->write_character(to_char_type(0x3A)); | |
15200 write_number(static_cast<std::uint32_t>(positive_number)); | |
15201 } | |
15202 else | |
15203 { | |
15204 oa->write_character(to_char_type(0x3B)); | |
15205 write_number(static_cast<std::uint64_t>(positive_number)); | |
15206 } | |
15207 } | |
15208 break; | |
15209 } | |
15210 | |
15211 case value_t::number_unsigned: | |
15212 { | |
15213 if (j.m_data.m_value.number_unsigned <= 0x17) | |
15214 { | |
15215 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); | |
15216 } | |
15217 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) | |
15218 { | |
15219 oa->write_character(to_char_type(0x18)); | |
15220 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); | |
15221 } | |
15222 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) | |
15223 { | |
15224 oa->write_character(to_char_type(0x19)); | |
15225 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned)); | |
15226 } | |
15227 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) | |
15228 { | |
15229 oa->write_character(to_char_type(0x1A)); | |
15230 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned)); | |
15231 } | |
15232 else | |
15233 { | |
15234 oa->write_character(to_char_type(0x1B)); | |
15235 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned)); | |
15236 } | |
15237 break; | |
15238 } | |
15239 | |
15240 case value_t::number_float: | |
15241 { | |
15242 if (std::isnan(j.m_data.m_value.number_float)) | |
15243 { | |
15244 // NaN is 0xf97e00 in CBOR | |
15245 oa->write_character(to_char_type(0xF9)); | |
15246 oa->write_character(to_char_type(0x7E)); | |
15247 oa->write_character(to_char_type(0x00)); | |
15248 } | |
15249 else if (std::isinf(j.m_data.m_value.number_float)) | |
15250 { | |
15251 // Infinity is 0xf97c00, -Infinity is 0xf9fc00 | |
15252 oa->write_character(to_char_type(0xf9)); | |
15253 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); | |
15254 oa->write_character(to_char_type(0x00)); | |
15255 } | |
15256 else | |
15257 { | |
15258 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); | |
15259 } | |
15260 break; | |
15261 } | |
15262 | |
15263 case value_t::string: | |
15264 { | |
15265 // step 1: write control byte and the string length | |
15266 const auto N = j.m_data.m_value.string->size(); | |
15267 if (N <= 0x17) | |
15268 { | |
15269 write_number(static_cast<std::uint8_t>(0x60 + N)); | |
15270 } | |
15271 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15272 { | |
15273 oa->write_character(to_char_type(0x78)); | |
15274 write_number(static_cast<std::uint8_t>(N)); | |
15275 } | |
15276 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15277 { | |
15278 oa->write_character(to_char_type(0x79)); | |
15279 write_number(static_cast<std::uint16_t>(N)); | |
15280 } | |
15281 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15282 { | |
15283 oa->write_character(to_char_type(0x7A)); | |
15284 write_number(static_cast<std::uint32_t>(N)); | |
15285 } | |
15286 // LCOV_EXCL_START | |
15287 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) | |
15288 { | |
15289 oa->write_character(to_char_type(0x7B)); | |
15290 write_number(static_cast<std::uint64_t>(N)); | |
15291 } | |
15292 // LCOV_EXCL_STOP | |
15293 | |
15294 // step 2: write the string | |
15295 oa->write_characters( | |
15296 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), | |
15297 j.m_data.m_value.string->size()); | |
15298 break; | |
15299 } | |
15300 | |
15301 case value_t::array: | |
15302 { | |
15303 // step 1: write control byte and the array size | |
15304 const auto N = j.m_data.m_value.array->size(); | |
15305 if (N <= 0x17) | |
15306 { | |
15307 write_number(static_cast<std::uint8_t>(0x80 + N)); | |
15308 } | |
15309 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15310 { | |
15311 oa->write_character(to_char_type(0x98)); | |
15312 write_number(static_cast<std::uint8_t>(N)); | |
15313 } | |
15314 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15315 { | |
15316 oa->write_character(to_char_type(0x99)); | |
15317 write_number(static_cast<std::uint16_t>(N)); | |
15318 } | |
15319 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15320 { | |
15321 oa->write_character(to_char_type(0x9A)); | |
15322 write_number(static_cast<std::uint32_t>(N)); | |
15323 } | |
15324 // LCOV_EXCL_START | |
15325 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) | |
15326 { | |
15327 oa->write_character(to_char_type(0x9B)); | |
15328 write_number(static_cast<std::uint64_t>(N)); | |
15329 } | |
15330 // LCOV_EXCL_STOP | |
15331 | |
15332 // step 2: write each element | |
15333 for (const auto& el : *j.m_data.m_value.array) | |
15334 { | |
15335 write_cbor(el); | |
15336 } | |
15337 break; | |
15338 } | |
15339 | |
15340 case value_t::binary: | |
15341 { | |
15342 if (j.m_data.m_value.binary->has_subtype()) | |
15343 { | |
15344 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) | |
15345 { | |
15346 write_number(static_cast<std::uint8_t>(0xd8)); | |
15347 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype())); | |
15348 } | |
15349 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) | |
15350 { | |
15351 write_number(static_cast<std::uint8_t>(0xd9)); | |
15352 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype())); | |
15353 } | |
15354 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) | |
15355 { | |
15356 write_number(static_cast<std::uint8_t>(0xda)); | |
15357 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype())); | |
15358 } | |
15359 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) | |
15360 { | |
15361 write_number(static_cast<std::uint8_t>(0xdb)); | |
15362 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype())); | |
15363 } | |
15364 } | |
15365 | |
15366 // step 1: write control byte and the binary array size | |
15367 const auto N = j.m_data.m_value.binary->size(); | |
15368 if (N <= 0x17) | |
15369 { | |
15370 write_number(static_cast<std::uint8_t>(0x40 + N)); | |
15371 } | |
15372 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15373 { | |
15374 oa->write_character(to_char_type(0x58)); | |
15375 write_number(static_cast<std::uint8_t>(N)); | |
15376 } | |
15377 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15378 { | |
15379 oa->write_character(to_char_type(0x59)); | |
15380 write_number(static_cast<std::uint16_t>(N)); | |
15381 } | |
15382 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15383 { | |
15384 oa->write_character(to_char_type(0x5A)); | |
15385 write_number(static_cast<std::uint32_t>(N)); | |
15386 } | |
15387 // LCOV_EXCL_START | |
15388 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) | |
15389 { | |
15390 oa->write_character(to_char_type(0x5B)); | |
15391 write_number(static_cast<std::uint64_t>(N)); | |
15392 } | |
15393 // LCOV_EXCL_STOP | |
15394 | |
15395 // step 2: write each element | |
15396 oa->write_characters( | |
15397 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), | |
15398 N); | |
15399 | |
15400 break; | |
15401 } | |
15402 | |
15403 case value_t::object: | |
15404 { | |
15405 // step 1: write control byte and the object size | |
15406 const auto N = j.m_data.m_value.object->size(); | |
15407 if (N <= 0x17) | |
15408 { | |
15409 write_number(static_cast<std::uint8_t>(0xA0 + N)); | |
15410 } | |
15411 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15412 { | |
15413 oa->write_character(to_char_type(0xB8)); | |
15414 write_number(static_cast<std::uint8_t>(N)); | |
15415 } | |
15416 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15417 { | |
15418 oa->write_character(to_char_type(0xB9)); | |
15419 write_number(static_cast<std::uint16_t>(N)); | |
15420 } | |
15421 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15422 { | |
15423 oa->write_character(to_char_type(0xBA)); | |
15424 write_number(static_cast<std::uint32_t>(N)); | |
15425 } | |
15426 // LCOV_EXCL_START | |
15427 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) | |
15428 { | |
15429 oa->write_character(to_char_type(0xBB)); | |
15430 write_number(static_cast<std::uint64_t>(N)); | |
15431 } | |
15432 // LCOV_EXCL_STOP | |
15433 | |
15434 // step 2: write each element | |
15435 for (const auto& el : *j.m_data.m_value.object) | |
15436 { | |
15437 write_cbor(el.first); | |
15438 write_cbor(el.second); | |
15439 } | |
15440 break; | |
15441 } | |
15442 | |
15443 case value_t::discarded: | |
15444 default: | |
15445 break; | |
15446 } | |
15447 } | |
15448 | |
15449 /*! | |
15450 @param[in] j JSON value to serialize | |
15451 */ | |
15452 void write_msgpack(const BasicJsonType& j) | |
15453 { | |
15454 switch (j.type()) | |
15455 { | |
15456 case value_t::null: // nil | |
15457 { | |
15458 oa->write_character(to_char_type(0xC0)); | |
15459 break; | |
15460 } | |
15461 | |
15462 case value_t::boolean: // true and false | |
15463 { | |
15464 oa->write_character(j.m_data.m_value.boolean | |
15465 ? to_char_type(0xC3) | |
15466 : to_char_type(0xC2)); | |
15467 break; | |
15468 } | |
15469 | |
15470 case value_t::number_integer: | |
15471 { | |
15472 if (j.m_data.m_value.number_integer >= 0) | |
15473 { | |
15474 // MessagePack does not differentiate between positive | |
15475 // signed integers and unsigned integers. Therefore, we used | |
15476 // the code from the value_t::number_unsigned case here. | |
15477 if (j.m_data.m_value.number_unsigned < 128) | |
15478 { | |
15479 // positive fixnum | |
15480 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15481 } | |
15482 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) | |
15483 { | |
15484 // uint 8 | |
15485 oa->write_character(to_char_type(0xCC)); | |
15486 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15487 } | |
15488 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) | |
15489 { | |
15490 // uint 16 | |
15491 oa->write_character(to_char_type(0xCD)); | |
15492 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); | |
15493 } | |
15494 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) | |
15495 { | |
15496 // uint 32 | |
15497 oa->write_character(to_char_type(0xCE)); | |
15498 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); | |
15499 } | |
15500 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) | |
15501 { | |
15502 // uint 64 | |
15503 oa->write_character(to_char_type(0xCF)); | |
15504 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); | |
15505 } | |
15506 } | |
15507 else | |
15508 { | |
15509 if (j.m_data.m_value.number_integer >= -32) | |
15510 { | |
15511 // negative fixnum | |
15512 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); | |
15513 } | |
15514 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() && | |
15515 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) | |
15516 { | |
15517 // int 8 | |
15518 oa->write_character(to_char_type(0xD0)); | |
15519 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); | |
15520 } | |
15521 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() && | |
15522 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) | |
15523 { | |
15524 // int 16 | |
15525 oa->write_character(to_char_type(0xD1)); | |
15526 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer)); | |
15527 } | |
15528 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() && | |
15529 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) | |
15530 { | |
15531 // int 32 | |
15532 oa->write_character(to_char_type(0xD2)); | |
15533 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer)); | |
15534 } | |
15535 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() && | |
15536 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) | |
15537 { | |
15538 // int 64 | |
15539 oa->write_character(to_char_type(0xD3)); | |
15540 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer)); | |
15541 } | |
15542 } | |
15543 break; | |
15544 } | |
15545 | |
15546 case value_t::number_unsigned: | |
15547 { | |
15548 if (j.m_data.m_value.number_unsigned < 128) | |
15549 { | |
15550 // positive fixnum | |
15551 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15552 } | |
15553 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) | |
15554 { | |
15555 // uint 8 | |
15556 oa->write_character(to_char_type(0xCC)); | |
15557 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); | |
15558 } | |
15559 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) | |
15560 { | |
15561 // uint 16 | |
15562 oa->write_character(to_char_type(0xCD)); | |
15563 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); | |
15564 } | |
15565 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) | |
15566 { | |
15567 // uint 32 | |
15568 oa->write_character(to_char_type(0xCE)); | |
15569 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); | |
15570 } | |
15571 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) | |
15572 { | |
15573 // uint 64 | |
15574 oa->write_character(to_char_type(0xCF)); | |
15575 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); | |
15576 } | |
15577 break; | |
15578 } | |
15579 | |
15580 case value_t::number_float: | |
15581 { | |
15582 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); | |
15583 break; | |
15584 } | |
15585 | |
15586 case value_t::string: | |
15587 { | |
15588 // step 1: write control byte and the string length | |
15589 const auto N = j.m_data.m_value.string->size(); | |
15590 if (N <= 31) | |
15591 { | |
15592 // fixstr | |
15593 write_number(static_cast<std::uint8_t>(0xA0 | N)); | |
15594 } | |
15595 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15596 { | |
15597 // str 8 | |
15598 oa->write_character(to_char_type(0xD9)); | |
15599 write_number(static_cast<std::uint8_t>(N)); | |
15600 } | |
15601 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15602 { | |
15603 // str 16 | |
15604 oa->write_character(to_char_type(0xDA)); | |
15605 write_number(static_cast<std::uint16_t>(N)); | |
15606 } | |
15607 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15608 { | |
15609 // str 32 | |
15610 oa->write_character(to_char_type(0xDB)); | |
15611 write_number(static_cast<std::uint32_t>(N)); | |
15612 } | |
15613 | |
15614 // step 2: write the string | |
15615 oa->write_characters( | |
15616 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), | |
15617 j.m_data.m_value.string->size()); | |
15618 break; | |
15619 } | |
15620 | |
15621 case value_t::array: | |
15622 { | |
15623 // step 1: write control byte and the array size | |
15624 const auto N = j.m_data.m_value.array->size(); | |
15625 if (N <= 15) | |
15626 { | |
15627 // fixarray | |
15628 write_number(static_cast<std::uint8_t>(0x90 | N)); | |
15629 } | |
15630 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15631 { | |
15632 // array 16 | |
15633 oa->write_character(to_char_type(0xDC)); | |
15634 write_number(static_cast<std::uint16_t>(N)); | |
15635 } | |
15636 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15637 { | |
15638 // array 32 | |
15639 oa->write_character(to_char_type(0xDD)); | |
15640 write_number(static_cast<std::uint32_t>(N)); | |
15641 } | |
15642 | |
15643 // step 2: write each element | |
15644 for (const auto& el : *j.m_data.m_value.array) | |
15645 { | |
15646 write_msgpack(el); | |
15647 } | |
15648 break; | |
15649 } | |
15650 | |
15651 case value_t::binary: | |
15652 { | |
15653 // step 0: determine if the binary type has a set subtype to | |
15654 // determine whether or not to use the ext or fixext types | |
15655 const bool use_ext = j.m_data.m_value.binary->has_subtype(); | |
15656 | |
15657 // step 1: write control byte and the byte string length | |
15658 const auto N = j.m_data.m_value.binary->size(); | |
15659 if (N <= (std::numeric_limits<std::uint8_t>::max)()) | |
15660 { | |
15661 std::uint8_t output_type{}; | |
15662 bool fixed = true; | |
15663 if (use_ext) | |
15664 { | |
15665 switch (N) | |
15666 { | |
15667 case 1: | |
15668 output_type = 0xD4; // fixext 1 | |
15669 break; | |
15670 case 2: | |
15671 output_type = 0xD5; // fixext 2 | |
15672 break; | |
15673 case 4: | |
15674 output_type = 0xD6; // fixext 4 | |
15675 break; | |
15676 case 8: | |
15677 output_type = 0xD7; // fixext 8 | |
15678 break; | |
15679 case 16: | |
15680 output_type = 0xD8; // fixext 16 | |
15681 break; | |
15682 default: | |
15683 output_type = 0xC7; // ext 8 | |
15684 fixed = false; | |
15685 break; | |
15686 } | |
15687 | |
15688 } | |
15689 else | |
15690 { | |
15691 output_type = 0xC4; // bin 8 | |
15692 fixed = false; | |
15693 } | |
15694 | |
15695 oa->write_character(to_char_type(output_type)); | |
15696 if (!fixed) | |
15697 { | |
15698 write_number(static_cast<std::uint8_t>(N)); | |
15699 } | |
15700 } | |
15701 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15702 { | |
15703 const std::uint8_t output_type = use_ext | |
15704 ? 0xC8 // ext 16 | |
15705 : 0xC5; // bin 16 | |
15706 | |
15707 oa->write_character(to_char_type(output_type)); | |
15708 write_number(static_cast<std::uint16_t>(N)); | |
15709 } | |
15710 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15711 { | |
15712 const std::uint8_t output_type = use_ext | |
15713 ? 0xC9 // ext 32 | |
15714 : 0xC6; // bin 32 | |
15715 | |
15716 oa->write_character(to_char_type(output_type)); | |
15717 write_number(static_cast<std::uint32_t>(N)); | |
15718 } | |
15719 | |
15720 // step 1.5: if this is an ext type, write the subtype | |
15721 if (use_ext) | |
15722 { | |
15723 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype())); | |
15724 } | |
15725 | |
15726 // step 2: write the byte string | |
15727 oa->write_characters( | |
15728 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), | |
15729 N); | |
15730 | |
15731 break; | |
15732 } | |
15733 | |
15734 case value_t::object: | |
15735 { | |
15736 // step 1: write control byte and the object size | |
15737 const auto N = j.m_data.m_value.object->size(); | |
15738 if (N <= 15) | |
15739 { | |
15740 // fixmap | |
15741 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF))); | |
15742 } | |
15743 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) | |
15744 { | |
15745 // map 16 | |
15746 oa->write_character(to_char_type(0xDE)); | |
15747 write_number(static_cast<std::uint16_t>(N)); | |
15748 } | |
15749 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) | |
15750 { | |
15751 // map 32 | |
15752 oa->write_character(to_char_type(0xDF)); | |
15753 write_number(static_cast<std::uint32_t>(N)); | |
15754 } | |
15755 | |
15756 // step 2: write each element | |
15757 for (const auto& el : *j.m_data.m_value.object) | |
15758 { | |
15759 write_msgpack(el.first); | |
15760 write_msgpack(el.second); | |
15761 } | |
15762 break; | |
15763 } | |
15764 | |
15765 case value_t::discarded: | |
15766 default: | |
15767 break; | |
15768 } | |
15769 } | |
15770 | |
15771 /*! | |
15772 @param[in] j JSON value to serialize | |
15773 @param[in] use_count whether to use '#' prefixes (optimized format) | |
15774 @param[in] use_type whether to use '$' prefixes (optimized format) | |
15775 @param[in] add_prefix whether prefixes need to be used for this value | |
15776 @param[in] use_bjdata whether write in BJData format, default is false | |
15777 */ | |
15778 void write_ubjson(const BasicJsonType& j, const bool use_count, | |
15779 const bool use_type, const bool add_prefix = true, | |
15780 const bool use_bjdata = false) | |
15781 { | |
15782 switch (j.type()) | |
15783 { | |
15784 case value_t::null: | |
15785 { | |
15786 if (add_prefix) | |
15787 { | |
15788 oa->write_character(to_char_type('Z')); | |
15789 } | |
15790 break; | |
15791 } | |
15792 | |
15793 case value_t::boolean: | |
15794 { | |
15795 if (add_prefix) | |
15796 { | |
15797 oa->write_character(j.m_data.m_value.boolean | |
15798 ? to_char_type('T') | |
15799 : to_char_type('F')); | |
15800 } | |
15801 break; | |
15802 } | |
15803 | |
15804 case value_t::number_integer: | |
15805 { | |
15806 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); | |
15807 break; | |
15808 } | |
15809 | |
15810 case value_t::number_unsigned: | |
15811 { | |
15812 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); | |
15813 break; | |
15814 } | |
15815 | |
15816 case value_t::number_float: | |
15817 { | |
15818 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); | |
15819 break; | |
15820 } | |
15821 | |
15822 case value_t::string: | |
15823 { | |
15824 if (add_prefix) | |
15825 { | |
15826 oa->write_character(to_char_type('S')); | |
15827 } | |
15828 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); | |
15829 oa->write_characters( | |
15830 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), | |
15831 j.m_data.m_value.string->size()); | |
15832 break; | |
15833 } | |
15834 | |
15835 case value_t::array: | |
15836 { | |
15837 if (add_prefix) | |
15838 { | |
15839 oa->write_character(to_char_type('[')); | |
15840 } | |
15841 | |
15842 bool prefix_required = true; | |
15843 if (use_type && !j.m_data.m_value.array->empty()) | |
15844 { | |
15845 JSON_ASSERT(use_count); | |
15846 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); | |
15847 const bool same_prefix = std::all_of(j.begin() + 1, j.end(), | |
15848 [this, first_prefix, use_bjdata](const BasicJsonType & v) | |
15849 { | |
15850 return ubjson_prefix(v, use_bjdata) == first_prefix; | |
15851 }); | |
15852 | |
15853 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type | |
15854 | |
15855 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) | |
15856 { | |
15857 prefix_required = false; | |
15858 oa->write_character(to_char_type('$')); | |
15859 oa->write_character(first_prefix); | |
15860 } | |
15861 } | |
15862 | |
15863 if (use_count) | |
15864 { | |
15865 oa->write_character(to_char_type('#')); | |
15866 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); | |
15867 } | |
15868 | |
15869 for (const auto& el : *j.m_data.m_value.array) | |
15870 { | |
15871 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); | |
15872 } | |
15873 | |
15874 if (!use_count) | |
15875 { | |
15876 oa->write_character(to_char_type(']')); | |
15877 } | |
15878 | |
15879 break; | |
15880 } | |
15881 | |
15882 case value_t::binary: | |
15883 { | |
15884 if (add_prefix) | |
15885 { | |
15886 oa->write_character(to_char_type('[')); | |
15887 } | |
15888 | |
15889 if (use_type && !j.m_data.m_value.binary->empty()) | |
15890 { | |
15891 JSON_ASSERT(use_count); | |
15892 oa->write_character(to_char_type('$')); | |
15893 oa->write_character('U'); | |
15894 } | |
15895 | |
15896 if (use_count) | |
15897 { | |
15898 oa->write_character(to_char_type('#')); | |
15899 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); | |
15900 } | |
15901 | |
15902 if (use_type) | |
15903 { | |
15904 oa->write_characters( | |
15905 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), | |
15906 j.m_data.m_value.binary->size()); | |
15907 } | |
15908 else | |
15909 { | |
15910 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) | |
15911 { | |
15912 oa->write_character(to_char_type('U')); | |
15913 oa->write_character(j.m_data.m_value.binary->data()[i]); | |
15914 } | |
15915 } | |
15916 | |
15917 if (!use_count) | |
15918 { | |
15919 oa->write_character(to_char_type(']')); | |
15920 } | |
15921 | |
15922 break; | |
15923 } | |
15924 | |
15925 case value_t::object: | |
15926 { | |
15927 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) | |
15928 { | |
15929 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) | |
15930 { | |
15931 break; | |
15932 } | |
15933 } | |
15934 | |
15935 if (add_prefix) | |
15936 { | |
15937 oa->write_character(to_char_type('{')); | |
15938 } | |
15939 | |
15940 bool prefix_required = true; | |
15941 if (use_type && !j.m_data.m_value.object->empty()) | |
15942 { | |
15943 JSON_ASSERT(use_count); | |
15944 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); | |
15945 const bool same_prefix = std::all_of(j.begin(), j.end(), | |
15946 [this, first_prefix, use_bjdata](const BasicJsonType & v) | |
15947 { | |
15948 return ubjson_prefix(v, use_bjdata) == first_prefix; | |
15949 }); | |
15950 | |
15951 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type | |
15952 | |
15953 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) | |
15954 { | |
15955 prefix_required = false; | |
15956 oa->write_character(to_char_type('$')); | |
15957 oa->write_character(first_prefix); | |
15958 } | |
15959 } | |
15960 | |
15961 if (use_count) | |
15962 { | |
15963 oa->write_character(to_char_type('#')); | |
15964 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); | |
15965 } | |
15966 | |
15967 for (const auto& el : *j.m_data.m_value.object) | |
15968 { | |
15969 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); | |
15970 oa->write_characters( | |
15971 reinterpret_cast<const CharType*>(el.first.c_str()), | |
15972 el.first.size()); | |
15973 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata); | |
15974 } | |
15975 | |
15976 if (!use_count) | |
15977 { | |
15978 oa->write_character(to_char_type('}')); | |
15979 } | |
15980 | |
15981 break; | |
15982 } | |
15983 | |
15984 case value_t::discarded: | |
15985 default: | |
15986 break; | |
15987 } | |
15988 } | |
15989 | |
15990 private: | |
15991 ////////// | |
15992 // BSON // | |
15993 ////////// | |
15994 | |
15995 /*! | |
15996 @return The size of a BSON document entry header, including the id marker | |
15997 and the entry name size (and its null-terminator). | |
15998 */ | |
15999 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) | |
16000 { | |
16001 const auto it = name.find(static_cast<typename string_t::value_type>(0)); | |
16002 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) | |
16003 { | |
16004 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j)); | |
16005 static_cast<void>(j); | |
16006 } | |
16007 | |
16008 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; | |
16009 } | |
16010 | |
16011 /*! | |
16012 @brief Writes the given @a element_type and @a name to the output adapter | |
16013 */ | |
16014 void write_bson_entry_header(const string_t& name, | |
16015 const std::uint8_t element_type) | |
16016 { | |
16017 oa->write_character(to_char_type(element_type)); // boolean | |
16018 oa->write_characters( | |
16019 reinterpret_cast<const CharType*>(name.c_str()), | |
16020 name.size() + 1u); | |
16021 } | |
16022 | |
16023 /*! | |
16024 @brief Writes a BSON element with key @a name and boolean value @a value | |
16025 */ | |
16026 void write_bson_boolean(const string_t& name, | |
16027 const bool value) | |
16028 { | |
16029 write_bson_entry_header(name, 0x08); | |
16030 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); | |
16031 } | |
16032 | |
16033 /*! | |
16034 @brief Writes a BSON element with key @a name and double value @a value | |
16035 */ | |
16036 void write_bson_double(const string_t& name, | |
16037 const double value) | |
16038 { | |
16039 write_bson_entry_header(name, 0x01); | |
16040 write_number<double>(value, true); | |
16041 } | |
16042 | |
16043 /*! | |
16044 @return The size of the BSON-encoded string in @a value | |
16045 */ | |
16046 static std::size_t calc_bson_string_size(const string_t& value) | |
16047 { | |
16048 return sizeof(std::int32_t) + value.size() + 1ul; | |
16049 } | |
16050 | |
16051 /*! | |
16052 @brief Writes a BSON element with key @a name and string value @a value | |
16053 */ | |
16054 void write_bson_string(const string_t& name, | |
16055 const string_t& value) | |
16056 { | |
16057 write_bson_entry_header(name, 0x02); | |
16058 | |
16059 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true); | |
16060 oa->write_characters( | |
16061 reinterpret_cast<const CharType*>(value.c_str()), | |
16062 value.size() + 1); | |
16063 } | |
16064 | |
16065 /*! | |
16066 @brief Writes a BSON element with key @a name and null value | |
16067 */ | |
16068 void write_bson_null(const string_t& name) | |
16069 { | |
16070 write_bson_entry_header(name, 0x0A); | |
16071 } | |
16072 | |
16073 /*! | |
16074 @return The size of the BSON-encoded integer @a value | |
16075 */ | |
16076 static std::size_t calc_bson_integer_size(const std::int64_t value) | |
16077 { | |
16078 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() | |
16079 ? sizeof(std::int32_t) | |
16080 : sizeof(std::int64_t); | |
16081 } | |
16082 | |
16083 /*! | |
16084 @brief Writes a BSON element with key @a name and integer @a value | |
16085 */ | |
16086 void write_bson_integer(const string_t& name, | |
16087 const std::int64_t value) | |
16088 { | |
16089 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()) | |
16090 { | |
16091 write_bson_entry_header(name, 0x10); // int32 | |
16092 write_number<std::int32_t>(static_cast<std::int32_t>(value), true); | |
16093 } | |
16094 else | |
16095 { | |
16096 write_bson_entry_header(name, 0x12); // int64 | |
16097 write_number<std::int64_t>(static_cast<std::int64_t>(value), true); | |
16098 } | |
16099 } | |
16100 | |
16101 /*! | |
16102 @return The size of the BSON-encoded unsigned integer in @a j | |
16103 */ | |
16104 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept | |
16105 { | |
16106 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | |
16107 ? sizeof(std::int32_t) | |
16108 : sizeof(std::int64_t); | |
16109 } | |
16110 | |
16111 /*! | |
16112 @brief Writes a BSON element with key @a name and unsigned @a value | |
16113 */ | |
16114 void write_bson_unsigned(const string_t& name, | |
16115 const BasicJsonType& j) | |
16116 { | |
16117 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | |
16118 { | |
16119 write_bson_entry_header(name, 0x10 /* int32 */); | |
16120 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true); | |
16121 } | |
16122 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) | |
16123 { | |
16124 write_bson_entry_header(name, 0x12 /* int64 */); | |
16125 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true); | |
16126 } | |
16127 else | |
16128 { | |
16129 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); | |
16130 } | |
16131 } | |
16132 | |
16133 /*! | |
16134 @brief Writes a BSON element with key @a name and object @a value | |
16135 */ | |
16136 void write_bson_object_entry(const string_t& name, | |
16137 const typename BasicJsonType::object_t& value) | |
16138 { | |
16139 write_bson_entry_header(name, 0x03); // object | |
16140 write_bson_object(value); | |
16141 } | |
16142 | |
16143 /*! | |
16144 @return The size of the BSON-encoded array @a value | |
16145 */ | |
16146 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) | |
16147 { | |
16148 std::size_t array_index = 0ul; | |
16149 | |
16150 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) | |
16151 { | |
16152 return result + calc_bson_element_size(std::to_string(array_index++), el); | |
16153 }); | |
16154 | |
16155 return sizeof(std::int32_t) + embedded_document_size + 1ul; | |
16156 } | |
16157 | |
16158 /*! | |
16159 @return The size of the BSON-encoded binary array @a value | |
16160 */ | |
16161 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) | |
16162 { | |
16163 return sizeof(std::int32_t) + value.size() + 1ul; | |
16164 } | |
16165 | |
16166 /*! | |
16167 @brief Writes a BSON element with key @a name and array @a value | |
16168 */ | |
16169 void write_bson_array(const string_t& name, | |
16170 const typename BasicJsonType::array_t& value) | |
16171 { | |
16172 write_bson_entry_header(name, 0x04); // array | |
16173 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true); | |
16174 | |
16175 std::size_t array_index = 0ul; | |
16176 | |
16177 for (const auto& el : value) | |
16178 { | |
16179 write_bson_element(std::to_string(array_index++), el); | |
16180 } | |
16181 | |
16182 oa->write_character(to_char_type(0x00)); | |
16183 } | |
16184 | |
16185 /*! | |
16186 @brief Writes a BSON element with key @a name and binary value @a value | |
16187 */ | |
16188 void write_bson_binary(const string_t& name, | |
16189 const binary_t& value) | |
16190 { | |
16191 write_bson_entry_header(name, 0x05); | |
16192 | |
16193 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true); | |
16194 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00)); | |
16195 | |
16196 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size()); | |
16197 } | |
16198 | |
16199 /*! | |
16200 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name | |
16201 @return The calculated size for the BSON document entry for @a j with the given @a name. | |
16202 */ | |
16203 static std::size_t calc_bson_element_size(const string_t& name, | |
16204 const BasicJsonType& j) | |
16205 { | |
16206 const auto header_size = calc_bson_entry_header_size(name, j); | |
16207 switch (j.type()) | |
16208 { | |
16209 case value_t::object: | |
16210 return header_size + calc_bson_object_size(*j.m_data.m_value.object); | |
16211 | |
16212 case value_t::array: | |
16213 return header_size + calc_bson_array_size(*j.m_data.m_value.array); | |
16214 | |
16215 case value_t::binary: | |
16216 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); | |
16217 | |
16218 case value_t::boolean: | |
16219 return header_size + 1ul; | |
16220 | |
16221 case value_t::number_float: | |
16222 return header_size + 8ul; | |
16223 | |
16224 case value_t::number_integer: | |
16225 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); | |
16226 | |
16227 case value_t::number_unsigned: | |
16228 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); | |
16229 | |
16230 case value_t::string: | |
16231 return header_size + calc_bson_string_size(*j.m_data.m_value.string); | |
16232 | |
16233 case value_t::null: | |
16234 return header_size + 0ul; | |
16235 | |
16236 // LCOV_EXCL_START | |
16237 case value_t::discarded: | |
16238 default: | |
16239 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) | |
16240 return 0ul; | |
16241 // LCOV_EXCL_STOP | |
16242 } | |
16243 } | |
16244 | |
16245 /*! | |
16246 @brief Serializes the JSON value @a j to BSON and associates it with the | |
16247 key @a name. | |
16248 @param name The name to associate with the JSON entity @a j within the | |
16249 current BSON document | |
16250 */ | |
16251 void write_bson_element(const string_t& name, | |
16252 const BasicJsonType& j) | |
16253 { | |
16254 switch (j.type()) | |
16255 { | |
16256 case value_t::object: | |
16257 return write_bson_object_entry(name, *j.m_data.m_value.object); | |
16258 | |
16259 case value_t::array: | |
16260 return write_bson_array(name, *j.m_data.m_value.array); | |
16261 | |
16262 case value_t::binary: | |
16263 return write_bson_binary(name, *j.m_data.m_value.binary); | |
16264 | |
16265 case value_t::boolean: | |
16266 return write_bson_boolean(name, j.m_data.m_value.boolean); | |
16267 | |
16268 case value_t::number_float: | |
16269 return write_bson_double(name, j.m_data.m_value.number_float); | |
16270 | |
16271 case value_t::number_integer: | |
16272 return write_bson_integer(name, j.m_data.m_value.number_integer); | |
16273 | |
16274 case value_t::number_unsigned: | |
16275 return write_bson_unsigned(name, j); | |
16276 | |
16277 case value_t::string: | |
16278 return write_bson_string(name, *j.m_data.m_value.string); | |
16279 | |
16280 case value_t::null: | |
16281 return write_bson_null(name); | |
16282 | |
16283 // LCOV_EXCL_START | |
16284 case value_t::discarded: | |
16285 default: | |
16286 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) | |
16287 return; | |
16288 // LCOV_EXCL_STOP | |
16289 } | |
16290 } | |
16291 | |
16292 /*! | |
16293 @brief Calculates the size of the BSON serialization of the given | |
16294 JSON-object @a j. | |
16295 @param[in] value JSON value to serialize | |
16296 @pre value.type() == value_t::object | |
16297 */ | |
16298 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) | |
16299 { | |
16300 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), | |
16301 [](size_t result, const typename BasicJsonType::object_t::value_type & el) | |
16302 { | |
16303 return result += calc_bson_element_size(el.first, el.second); | |
16304 }); | |
16305 | |
16306 return sizeof(std::int32_t) + document_size + 1ul; | |
16307 } | |
16308 | |
16309 /*! | |
16310 @param[in] value JSON value to serialize | |
16311 @pre value.type() == value_t::object | |
16312 */ | |
16313 void write_bson_object(const typename BasicJsonType::object_t& value) | |
16314 { | |
16315 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true); | |
16316 | |
16317 for (const auto& el : value) | |
16318 { | |
16319 write_bson_element(el.first, el.second); | |
16320 } | |
16321 | |
16322 oa->write_character(to_char_type(0x00)); | |
16323 } | |
16324 | |
16325 ////////// | |
16326 // CBOR // | |
16327 ////////// | |
16328 | |
16329 static constexpr CharType get_cbor_float_prefix(float /*unused*/) | |
16330 { | |
16331 return to_char_type(0xFA); // Single-Precision Float | |
16332 } | |
16333 | |
16334 static constexpr CharType get_cbor_float_prefix(double /*unused*/) | |
16335 { | |
16336 return to_char_type(0xFB); // Double-Precision Float | |
16337 } | |
16338 | |
16339 ///////////// | |
16340 // MsgPack // | |
16341 ///////////// | |
16342 | |
16343 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) | |
16344 { | |
16345 return to_char_type(0xCA); // float 32 | |
16346 } | |
16347 | |
16348 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) | |
16349 { | |
16350 return to_char_type(0xCB); // float 64 | |
16351 } | |
16352 | |
16353 //////////// | |
16354 // UBJSON // | |
16355 //////////// | |
16356 | |
16357 // UBJSON: write number (floating point) | |
16358 template<typename NumberType, typename std::enable_if< | |
16359 std::is_floating_point<NumberType>::value, int>::type = 0> | |
16360 void write_number_with_ubjson_prefix(const NumberType n, | |
16361 const bool add_prefix, | |
16362 const bool use_bjdata) | |
16363 { | |
16364 if (add_prefix) | |
16365 { | |
16366 oa->write_character(get_ubjson_float_prefix(n)); | |
16367 } | |
16368 write_number(n, use_bjdata); | |
16369 } | |
16370 | |
16371 // UBJSON: write number (unsigned integer) | |
16372 template<typename NumberType, typename std::enable_if< | |
16373 std::is_unsigned<NumberType>::value, int>::type = 0> | |
16374 void write_number_with_ubjson_prefix(const NumberType n, | |
16375 const bool add_prefix, | |
16376 const bool use_bjdata) | |
16377 { | |
16378 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) | |
16379 { | |
16380 if (add_prefix) | |
16381 { | |
16382 oa->write_character(to_char_type('i')); // int8 | |
16383 } | |
16384 write_number(static_cast<std::uint8_t>(n), use_bjdata); | |
16385 } | |
16386 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) | |
16387 { | |
16388 if (add_prefix) | |
16389 { | |
16390 oa->write_character(to_char_type('U')); // uint8 | |
16391 } | |
16392 write_number(static_cast<std::uint8_t>(n), use_bjdata); | |
16393 } | |
16394 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) | |
16395 { | |
16396 if (add_prefix) | |
16397 { | |
16398 oa->write_character(to_char_type('I')); // int16 | |
16399 } | |
16400 write_number(static_cast<std::int16_t>(n), use_bjdata); | |
16401 } | |
16402 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) | |
16403 { | |
16404 if (add_prefix) | |
16405 { | |
16406 oa->write_character(to_char_type('u')); // uint16 - bjdata only | |
16407 } | |
16408 write_number(static_cast<std::uint16_t>(n), use_bjdata); | |
16409 } | |
16410 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | |
16411 { | |
16412 if (add_prefix) | |
16413 { | |
16414 oa->write_character(to_char_type('l')); // int32 | |
16415 } | |
16416 write_number(static_cast<std::int32_t>(n), use_bjdata); | |
16417 } | |
16418 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) | |
16419 { | |
16420 if (add_prefix) | |
16421 { | |
16422 oa->write_character(to_char_type('m')); // uint32 - bjdata only | |
16423 } | |
16424 write_number(static_cast<std::uint32_t>(n), use_bjdata); | |
16425 } | |
16426 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) | |
16427 { | |
16428 if (add_prefix) | |
16429 { | |
16430 oa->write_character(to_char_type('L')); // int64 | |
16431 } | |
16432 write_number(static_cast<std::int64_t>(n), use_bjdata); | |
16433 } | |
16434 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) | |
16435 { | |
16436 if (add_prefix) | |
16437 { | |
16438 oa->write_character(to_char_type('M')); // uint64 - bjdata only | |
16439 } | |
16440 write_number(static_cast<std::uint64_t>(n), use_bjdata); | |
16441 } | |
16442 else | |
16443 { | |
16444 if (add_prefix) | |
16445 { | |
16446 oa->write_character(to_char_type('H')); // high-precision number | |
16447 } | |
16448 | |
16449 const auto number = BasicJsonType(n).dump(); | |
16450 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); | |
16451 for (std::size_t i = 0; i < number.size(); ++i) | |
16452 { | |
16453 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); | |
16454 } | |
16455 } | |
16456 } | |
16457 | |
16458 // UBJSON: write number (signed integer) | |
16459 template < typename NumberType, typename std::enable_if < | |
16460 std::is_signed<NumberType>::value&& | |
16461 !std::is_floating_point<NumberType>::value, int >::type = 0 > | |
16462 void write_number_with_ubjson_prefix(const NumberType n, | |
16463 const bool add_prefix, | |
16464 const bool use_bjdata) | |
16465 { | |
16466 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) | |
16467 { | |
16468 if (add_prefix) | |
16469 { | |
16470 oa->write_character(to_char_type('i')); // int8 | |
16471 } | |
16472 write_number(static_cast<std::int8_t>(n), use_bjdata); | |
16473 } | |
16474 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) | |
16475 { | |
16476 if (add_prefix) | |
16477 { | |
16478 oa->write_character(to_char_type('U')); // uint8 | |
16479 } | |
16480 write_number(static_cast<std::uint8_t>(n), use_bjdata); | |
16481 } | |
16482 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) | |
16483 { | |
16484 if (add_prefix) | |
16485 { | |
16486 oa->write_character(to_char_type('I')); // int16 | |
16487 } | |
16488 write_number(static_cast<std::int16_t>(n), use_bjdata); | |
16489 } | |
16490 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)()))) | |
16491 { | |
16492 if (add_prefix) | |
16493 { | |
16494 oa->write_character(to_char_type('u')); // uint16 - bjdata only | |
16495 } | |
16496 write_number(static_cast<uint16_t>(n), use_bjdata); | |
16497 } | |
16498 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) | |
16499 { | |
16500 if (add_prefix) | |
16501 { | |
16502 oa->write_character(to_char_type('l')); // int32 | |
16503 } | |
16504 write_number(static_cast<std::int32_t>(n), use_bjdata); | |
16505 } | |
16506 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)()))) | |
16507 { | |
16508 if (add_prefix) | |
16509 { | |
16510 oa->write_character(to_char_type('m')); // uint32 - bjdata only | |
16511 } | |
16512 write_number(static_cast<uint32_t>(n), use_bjdata); | |
16513 } | |
16514 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) | |
16515 { | |
16516 if (add_prefix) | |
16517 { | |
16518 oa->write_character(to_char_type('L')); // int64 | |
16519 } | |
16520 write_number(static_cast<std::int64_t>(n), use_bjdata); | |
16521 } | |
16522 // LCOV_EXCL_START | |
16523 else | |
16524 { | |
16525 if (add_prefix) | |
16526 { | |
16527 oa->write_character(to_char_type('H')); // high-precision number | |
16528 } | |
16529 | |
16530 const auto number = BasicJsonType(n).dump(); | |
16531 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); | |
16532 for (std::size_t i = 0; i < number.size(); ++i) | |
16533 { | |
16534 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); | |
16535 } | |
16536 } | |
16537 // LCOV_EXCL_STOP | |
16538 } | |
16539 | |
16540 /*! | |
16541 @brief determine the type prefix of container values | |
16542 */ | |
16543 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept | |
16544 { | |
16545 switch (j.type()) | |
16546 { | |
16547 case value_t::null: | |
16548 return 'Z'; | |
16549 | |
16550 case value_t::boolean: | |
16551 return j.m_data.m_value.boolean ? 'T' : 'F'; | |
16552 | |
16553 case value_t::number_integer: | |
16554 { | |
16555 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) | |
16556 { | |
16557 return 'i'; | |
16558 } | |
16559 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) | |
16560 { | |
16561 return 'U'; | |
16562 } | |
16563 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) | |
16564 { | |
16565 return 'I'; | |
16566 } | |
16567 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())) | |
16568 { | |
16569 return 'u'; | |
16570 } | |
16571 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) | |
16572 { | |
16573 return 'l'; | |
16574 } | |
16575 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())) | |
16576 { | |
16577 return 'm'; | |
16578 } | |
16579 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) | |
16580 { | |
16581 return 'L'; | |
16582 } | |
16583 // anything else is treated as high-precision number | |
16584 return 'H'; // LCOV_EXCL_LINE | |
16585 } | |
16586 | |
16587 case value_t::number_unsigned: | |
16588 { | |
16589 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) | |
16590 { | |
16591 return 'i'; | |
16592 } | |
16593 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) | |
16594 { | |
16595 return 'U'; | |
16596 } | |
16597 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) | |
16598 { | |
16599 return 'I'; | |
16600 } | |
16601 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) | |
16602 { | |
16603 return 'u'; | |
16604 } | |
16605 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | |
16606 { | |
16607 return 'l'; | |
16608 } | |
16609 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) | |
16610 { | |
16611 return 'm'; | |
16612 } | |
16613 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) | |
16614 { | |
16615 return 'L'; | |
16616 } | |
16617 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) | |
16618 { | |
16619 return 'M'; | |
16620 } | |
16621 // anything else is treated as high-precision number | |
16622 return 'H'; // LCOV_EXCL_LINE | |
16623 } | |
16624 | |
16625 case value_t::number_float: | |
16626 return get_ubjson_float_prefix(j.m_data.m_value.number_float); | |
16627 | |
16628 case value_t::string: | |
16629 return 'S'; | |
16630 | |
16631 case value_t::array: // fallthrough | |
16632 case value_t::binary: | |
16633 return '['; | |
16634 | |
16635 case value_t::object: | |
16636 return '{'; | |
16637 | |
16638 case value_t::discarded: | |
16639 default: // discarded values | |
16640 return 'N'; | |
16641 } | |
16642 } | |
16643 | |
16644 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) | |
16645 { | |
16646 return 'd'; // float 32 | |
16647 } | |
16648 | |
16649 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) | |
16650 { | |
16651 return 'D'; // float 64 | |
16652 } | |
16653 | |
16654 /*! | |
16655 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid | |
16656 */ | |
16657 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type) | |
16658 { | |
16659 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'}, | |
16660 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'} | |
16661 }; | |
16662 | |
16663 string_t key = "_ArrayType_"; | |
16664 auto it = bjdtype.find(static_cast<string_t>(value.at(key))); | |
16665 if (it == bjdtype.end()) | |
16666 { | |
16667 return true; | |
16668 } | |
16669 CharType dtype = it->second; | |
16670 | |
16671 key = "_ArraySize_"; | |
16672 std::size_t len = (value.at(key).empty() ? 0 : 1); | |
16673 for (const auto& el : value.at(key)) | |
16674 { | |
16675 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned); | |
16676 } | |
16677 | |
16678 key = "_ArrayData_"; | |
16679 if (value.at(key).size() != len) | |
16680 { | |
16681 return true; | |
16682 } | |
16683 | |
16684 oa->write_character('['); | |
16685 oa->write_character('$'); | |
16686 oa->write_character(dtype); | |
16687 oa->write_character('#'); | |
16688 | |
16689 key = "_ArraySize_"; | |
16690 write_ubjson(value.at(key), use_count, use_type, true, true); | |
16691 | |
16692 key = "_ArrayData_"; | |
16693 if (dtype == 'U' || dtype == 'C') | |
16694 { | |
16695 for (const auto& el : value.at(key)) | |
16696 { | |
16697 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true); | |
16698 } | |
16699 } | |
16700 else if (dtype == 'i') | |
16701 { | |
16702 for (const auto& el : value.at(key)) | |
16703 { | |
16704 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true); | |
16705 } | |
16706 } | |
16707 else if (dtype == 'u') | |
16708 { | |
16709 for (const auto& el : value.at(key)) | |
16710 { | |
16711 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true); | |
16712 } | |
16713 } | |
16714 else if (dtype == 'I') | |
16715 { | |
16716 for (const auto& el : value.at(key)) | |
16717 { | |
16718 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true); | |
16719 } | |
16720 } | |
16721 else if (dtype == 'm') | |
16722 { | |
16723 for (const auto& el : value.at(key)) | |
16724 { | |
16725 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true); | |
16726 } | |
16727 } | |
16728 else if (dtype == 'l') | |
16729 { | |
16730 for (const auto& el : value.at(key)) | |
16731 { | |
16732 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true); | |
16733 } | |
16734 } | |
16735 else if (dtype == 'M') | |
16736 { | |
16737 for (const auto& el : value.at(key)) | |
16738 { | |
16739 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true); | |
16740 } | |
16741 } | |
16742 else if (dtype == 'L') | |
16743 { | |
16744 for (const auto& el : value.at(key)) | |
16745 { | |
16746 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true); | |
16747 } | |
16748 } | |
16749 else if (dtype == 'd') | |
16750 { | |
16751 for (const auto& el : value.at(key)) | |
16752 { | |
16753 write_number(static_cast<float>(el.m_data.m_value.number_float), true); | |
16754 } | |
16755 } | |
16756 else if (dtype == 'D') | |
16757 { | |
16758 for (const auto& el : value.at(key)) | |
16759 { | |
16760 write_number(static_cast<double>(el.m_data.m_value.number_float), true); | |
16761 } | |
16762 } | |
16763 return false; | |
16764 } | |
16765 | |
16766 /////////////////////// | |
16767 // Utility functions // | |
16768 /////////////////////// | |
16769 | |
16770 /* | |
16771 @brief write a number to output input | |
16772 @param[in] n number of type @a NumberType | |
16773 @param[in] OutputIsLittleEndian Set to true if output data is | |
16774 required to be little endian | |
16775 @tparam NumberType the type of the number | |
16776 | |
16777 @note This function needs to respect the system's endianness, because bytes | |
16778 in CBOR, MessagePack, and UBJSON are stored in network order (big | |
16779 endian) and therefore need reordering on little endian systems. | |
16780 On the other hand, BSON and BJData use little endian and should reorder | |
16781 on big endian systems. | |
16782 */ | |
16783 template<typename NumberType> | |
16784 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) | |
16785 { | |
16786 // step 1: write number to array of length NumberType | |
16787 std::array<CharType, sizeof(NumberType)> vec{}; | |
16788 std::memcpy(vec.data(), &n, sizeof(NumberType)); | |
16789 | |
16790 // step 2: write array to output (with possible reordering) | |
16791 if (is_little_endian != OutputIsLittleEndian) | |
16792 { | |
16793 // reverse byte order prior to conversion if necessary | |
16794 std::reverse(vec.begin(), vec.end()); | |
16795 } | |
16796 | |
16797 oa->write_characters(vec.data(), sizeof(NumberType)); | |
16798 } | |
16799 | |
16800 void write_compact_float(const number_float_t n, detail::input_format_t format) | |
16801 { | |
16802 #ifdef __GNUC__ | |
16803 #pragma GCC diagnostic push | |
16804 #pragma GCC diagnostic ignored "-Wfloat-equal" | |
16805 #endif | |
16806 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) && | |
16807 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) && | |
16808 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)) | |
16809 { | |
16810 oa->write_character(format == detail::input_format_t::cbor | |
16811 ? get_cbor_float_prefix(static_cast<float>(n)) | |
16812 : get_msgpack_float_prefix(static_cast<float>(n))); | |
16813 write_number(static_cast<float>(n)); | |
16814 } | |
16815 else | |
16816 { | |
16817 oa->write_character(format == detail::input_format_t::cbor | |
16818 ? get_cbor_float_prefix(n) | |
16819 : get_msgpack_float_prefix(n)); | |
16820 write_number(n); | |
16821 } | |
16822 #ifdef __GNUC__ | |
16823 #pragma GCC diagnostic pop | |
16824 #endif | |
16825 } | |
16826 | |
16827 public: | |
16828 // The following to_char_type functions are implement the conversion | |
16829 // between uint8_t and CharType. In case CharType is not unsigned, | |
16830 // such a conversion is required to allow values greater than 128. | |
16831 // See <https://github.com/nlohmann/json/issues/1286> for a discussion. | |
16832 template < typename C = CharType, | |
16833 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr > | |
16834 static constexpr CharType to_char_type(std::uint8_t x) noexcept | |
16835 { | |
16836 return *reinterpret_cast<char*>(&x); | |
16837 } | |
16838 | |
16839 template < typename C = CharType, | |
16840 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr > | |
16841 static CharType to_char_type(std::uint8_t x) noexcept | |
16842 { | |
16843 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); | |
16844 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial"); | |
16845 CharType result; | |
16846 std::memcpy(&result, &x, sizeof(x)); | |
16847 return result; | |
16848 } | |
16849 | |
16850 template<typename C = CharType, | |
16851 enable_if_t<std::is_unsigned<C>::value>* = nullptr> | |
16852 static constexpr CharType to_char_type(std::uint8_t x) noexcept | |
16853 { | |
16854 return x; | |
16855 } | |
16856 | |
16857 template < typename InputCharType, typename C = CharType, | |
16858 enable_if_t < | |
16859 std::is_signed<C>::value && | |
16860 std::is_signed<char>::value && | |
16861 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value | |
16862 > * = nullptr > | |
16863 static constexpr CharType to_char_type(InputCharType x) noexcept | |
16864 { | |
16865 return x; | |
16866 } | |
16867 | |
16868 private: | |
16869 /// whether we can assume little endianness | |
16870 const bool is_little_endian = little_endianness(); | |
16871 | |
16872 /// the output | |
16873 output_adapter_t<CharType> oa = nullptr; | |
16874 }; | |
16875 | |
16876 } // namespace detail | |
16877 NLOHMANN_JSON_NAMESPACE_END | |
16878 | |
16879 // #include <nlohmann/detail/output/output_adapters.hpp> | |
16880 | |
16881 // #include <nlohmann/detail/output/serializer.hpp> | |
16882 // __ _____ _____ _____ | |
16883 // __| | __| | | | JSON for Modern C++ | |
16884 // | | |__ | | | | | | version 3.11.3 | |
16885 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
16886 // | |
16887 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> | |
16888 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
16889 // SPDX-License-Identifier: MIT | |
16890 | |
16891 | |
16892 | |
16893 #include <algorithm> // reverse, remove, fill, find, none_of | |
16894 #include <array> // array | |
16895 #include <clocale> // localeconv, lconv | |
16896 #include <cmath> // labs, isfinite, isnan, signbit | |
16897 #include <cstddef> // size_t, ptrdiff_t | |
16898 #include <cstdint> // uint8_t | |
16899 #include <cstdio> // snprintf | |
16900 #include <limits> // numeric_limits | |
16901 #include <string> // string, char_traits | |
16902 #include <iomanip> // setfill, setw | |
16903 #include <type_traits> // is_same | |
16904 #include <utility> // move | |
16905 | |
16906 // #include <nlohmann/detail/conversions/to_chars.hpp> | |
16907 // __ _____ _____ _____ | |
16908 // __| | __| | | | JSON for Modern C++ | |
16909 // | | |__ | | | | | | version 3.11.3 | |
16910 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
16911 // | |
16912 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> | |
16913 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
16914 // SPDX-License-Identifier: MIT | |
16915 | |
16916 | |
16917 | |
16918 #include <array> // array | |
16919 #include <cmath> // signbit, isfinite | |
16920 #include <cstdint> // intN_t, uintN_t | |
16921 #include <cstring> // memcpy, memmove | |
16922 #include <limits> // numeric_limits | |
16923 #include <type_traits> // conditional | |
16924 | |
16925 // #include <nlohmann/detail/macro_scope.hpp> | |
16926 | |
16927 | |
16928 NLOHMANN_JSON_NAMESPACE_BEGIN | |
16929 namespace detail | |
16930 { | |
16931 | |
16932 /*! | |
16933 @brief implements the Grisu2 algorithm for binary to decimal floating-point | |
16934 conversion. | |
16935 | |
16936 This implementation is a slightly modified version of the reference | |
16937 implementation which may be obtained from | |
16938 http://florian.loitsch.com/publications (bench.tar.gz). | |
16939 | |
16940 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. | |
16941 | |
16942 For a detailed description of the algorithm see: | |
16943 | |
16944 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with | |
16945 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming | |
16946 Language Design and Implementation, PLDI 2010 | |
16947 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", | |
16948 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language | |
16949 Design and Implementation, PLDI 1996 | |
16950 */ | |
16951 namespace dtoa_impl | |
16952 { | |
16953 | |
16954 template<typename Target, typename Source> | |
16955 Target reinterpret_bits(const Source source) | |
16956 { | |
16957 static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); | |
16958 | |
16959 Target target; | |
16960 std::memcpy(&target, &source, sizeof(Source)); | |
16961 return target; | |
16962 } | |
16963 | |
16964 struct diyfp // f * 2^e | |
16965 { | |
16966 static constexpr int kPrecision = 64; // = q | |
16967 | |
16968 std::uint64_t f = 0; | |
16969 int e = 0; | |
16970 | |
16971 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} | |
16972 | |
16973 /*! | |
16974 @brief returns x - y | |
16975 @pre x.e == y.e and x.f >= y.f | |
16976 */ | |
16977 static diyfp sub(const diyfp& x, const diyfp& y) noexcept | |
16978 { | |
16979 JSON_ASSERT(x.e == y.e); | |
16980 JSON_ASSERT(x.f >= y.f); | |
16981 | |
16982 return {x.f - y.f, x.e}; | |
16983 } | |
16984 | |
16985 /*! | |
16986 @brief returns x * y | |
16987 @note The result is rounded. (Only the upper q bits are returned.) | |
16988 */ | |
16989 static diyfp mul(const diyfp& x, const diyfp& y) noexcept | |
16990 { | |
16991 static_assert(kPrecision == 64, "internal error"); | |
16992 | |
16993 // Computes: | |
16994 // f = round((x.f * y.f) / 2^q) | |
16995 // e = x.e + y.e + q | |
16996 | |
16997 // Emulate the 64-bit * 64-bit multiplication: | |
16998 // | |
16999 // p = u * v | |
17000 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) | |
17001 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) | |
17002 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) | |
17003 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) | |
17004 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) | |
17005 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) | |
17006 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) | |
17007 // | |
17008 // (Since Q might be larger than 2^32 - 1) | |
17009 // | |
17010 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) | |
17011 // | |
17012 // (Q_hi + H does not overflow a 64-bit int) | |
17013 // | |
17014 // = p_lo + 2^64 p_hi | |
17015 | |
17016 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; | |
17017 const std::uint64_t u_hi = x.f >> 32u; | |
17018 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; | |
17019 const std::uint64_t v_hi = y.f >> 32u; | |
17020 | |
17021 const std::uint64_t p0 = u_lo * v_lo; | |
17022 const std::uint64_t p1 = u_lo * v_hi; | |
17023 const std::uint64_t p2 = u_hi * v_lo; | |
17024 const std::uint64_t p3 = u_hi * v_hi; | |
17025 | |
17026 const std::uint64_t p0_hi = p0 >> 32u; | |
17027 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; | |
17028 const std::uint64_t p1_hi = p1 >> 32u; | |
17029 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; | |
17030 const std::uint64_t p2_hi = p2 >> 32u; | |
17031 | |
17032 std::uint64_t Q = p0_hi + p1_lo + p2_lo; | |
17033 | |
17034 // The full product might now be computed as | |
17035 // | |
17036 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) | |
17037 // p_lo = p0_lo + (Q << 32) | |
17038 // | |
17039 // But in this particular case here, the full p_lo is not required. | |
17040 // Effectively we only need to add the highest bit in p_lo to p_hi (and | |
17041 // Q_hi + 1 does not overflow). | |
17042 | |
17043 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up | |
17044 | |
17045 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); | |
17046 | |
17047 return {h, x.e + y.e + 64}; | |
17048 } | |
17049 | |
17050 /*! | |
17051 @brief normalize x such that the significand is >= 2^(q-1) | |
17052 @pre x.f != 0 | |
17053 */ | |
17054 static diyfp normalize(diyfp x) noexcept | |
17055 { | |
17056 JSON_ASSERT(x.f != 0); | |
17057 | |
17058 while ((x.f >> 63u) == 0) | |
17059 { | |
17060 x.f <<= 1u; | |
17061 x.e--; | |
17062 } | |
17063 | |
17064 return x; | |
17065 } | |
17066 | |
17067 /*! | |
17068 @brief normalize x such that the result has the exponent E | |
17069 @pre e >= x.e and the upper e - x.e bits of x.f must be zero. | |
17070 */ | |
17071 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept | |
17072 { | |
17073 const int delta = x.e - target_exponent; | |
17074 | |
17075 JSON_ASSERT(delta >= 0); | |
17076 JSON_ASSERT(((x.f << delta) >> delta) == x.f); | |
17077 | |
17078 return {x.f << delta, target_exponent}; | |
17079 } | |
17080 }; | |
17081 | |
17082 struct boundaries | |
17083 { | |
17084 diyfp w; | |
17085 diyfp minus; | |
17086 diyfp plus; | |
17087 }; | |
17088 | |
17089 /*! | |
17090 Compute the (normalized) diyfp representing the input number 'value' and its | |
17091 boundaries. | |
17092 | |
17093 @pre value must be finite and positive | |
17094 */ | |
17095 template<typename FloatType> | |
17096 boundaries compute_boundaries(FloatType value) | |
17097 { | |
17098 JSON_ASSERT(std::isfinite(value)); | |
17099 JSON_ASSERT(value > 0); | |
17100 | |
17101 // Convert the IEEE representation into a diyfp. | |
17102 // | |
17103 // If v is denormal: | |
17104 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) | |
17105 // If v is normalized: | |
17106 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) | |
17107 | |
17108 static_assert(std::numeric_limits<FloatType>::is_iec559, | |
17109 "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); | |
17110 | |
17111 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) | |
17112 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); | |
17113 constexpr int kMinExp = 1 - kBias; | |
17114 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) | |
17115 | |
17116 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type; | |
17117 | |
17118 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value)); | |
17119 const std::uint64_t E = bits >> (kPrecision - 1); | |
17120 const std::uint64_t F = bits & (kHiddenBit - 1); | |
17121 | |
17122 const bool is_denormal = E == 0; | |
17123 const diyfp v = is_denormal | |
17124 ? diyfp(F, kMinExp) | |
17125 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); | |
17126 | |
17127 // Compute the boundaries m- and m+ of the floating-point value | |
17128 // v = f * 2^e. | |
17129 // | |
17130 // Determine v- and v+, the floating-point predecessor and successor if v, | |
17131 // respectively. | |
17132 // | |
17133 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) | |
17134 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) | |
17135 // | |
17136 // v+ = v + 2^e | |
17137 // | |
17138 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ | |
17139 // between m- and m+ round to v, regardless of how the input rounding | |
17140 // algorithm breaks ties. | |
17141 // | |
17142 // ---+-------------+-------------+-------------+-------------+--- (A) | |
17143 // v- m- v m+ v+ | |
17144 // | |
17145 // -----------------+------+------+-------------+-------------+--- (B) | |
17146 // v- m- v m+ v+ | |
17147 | |
17148 const bool lower_boundary_is_closer = F == 0 && E > 1; | |
17149 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); | |
17150 const diyfp m_minus = lower_boundary_is_closer | |
17151 ? diyfp(4 * v.f - 1, v.e - 2) // (B) | |
17152 : diyfp(2 * v.f - 1, v.e - 1); // (A) | |
17153 | |
17154 // Determine the normalized w+ = m+. | |
17155 const diyfp w_plus = diyfp::normalize(m_plus); | |
17156 | |
17157 // Determine w- = m- such that e_(w-) = e_(w+). | |
17158 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); | |
17159 | |
17160 return {diyfp::normalize(v), w_minus, w_plus}; | |
17161 } | |
17162 | |
17163 // Given normalized diyfp w, Grisu needs to find a (normalized) cached | |
17164 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies | |
17165 // within a certain range [alpha, gamma] (Definition 3.2 from [1]) | |
17166 // | |
17167 // alpha <= e = e_c + e_w + q <= gamma | |
17168 // | |
17169 // or | |
17170 // | |
17171 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q | |
17172 // <= f_c * f_w * 2^gamma | |
17173 // | |
17174 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies | |
17175 // | |
17176 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma | |
17177 // | |
17178 // or | |
17179 // | |
17180 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) | |
17181 // | |
17182 // The choice of (alpha,gamma) determines the size of the table and the form of | |
17183 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well | |
17184 // in practice: | |
17185 // | |
17186 // The idea is to cut the number c * w = f * 2^e into two parts, which can be | |
17187 // processed independently: An integral part p1, and a fractional part p2: | |
17188 // | |
17189 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e | |
17190 // = (f div 2^-e) + (f mod 2^-e) * 2^e | |
17191 // = p1 + p2 * 2^e | |
17192 // | |
17193 // The conversion of p1 into decimal form requires a series of divisions and | |
17194 // modulos by (a power of) 10. These operations are faster for 32-bit than for | |
17195 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be | |
17196 // achieved by choosing | |
17197 // | |
17198 // -e >= 32 or e <= -32 := gamma | |
17199 // | |
17200 // In order to convert the fractional part | |
17201 // | |
17202 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... | |
17203 // | |
17204 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits | |
17205 // d[-i] are extracted in order: | |
17206 // | |
17207 // (10 * p2) div 2^-e = d[-1] | |
17208 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ... | |
17209 // | |
17210 // The multiplication by 10 must not overflow. It is sufficient to choose | |
17211 // | |
17212 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. | |
17213 // | |
17214 // Since p2 = f mod 2^-e < 2^-e, | |
17215 // | |
17216 // -e <= 60 or e >= -60 := alpha | |
17217 | |
17218 constexpr int kAlpha = -60; | |
17219 constexpr int kGamma = -32; | |
17220 | |
17221 struct cached_power // c = f * 2^e ~= 10^k | |
17222 { | |
17223 std::uint64_t f; | |
17224 int e; | |
17225 int k; | |
17226 }; | |
17227 | |
17228 /*! | |
17229 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached | |
17230 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c | |
17231 satisfies (Definition 3.2 from [1]) | |
17232 | |
17233 alpha <= e_c + e + q <= gamma. | |
17234 */ | |
17235 inline cached_power get_cached_power_for_binary_exponent(int e) | |
17236 { | |
17237 // Now | |
17238 // | |
17239 // alpha <= e_c + e + q <= gamma (1) | |
17240 // ==> f_c * 2^alpha <= c * 2^e * 2^q | |
17241 // | |
17242 // and since the c's are normalized, 2^(q-1) <= f_c, | |
17243 // | |
17244 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) | |
17245 // ==> 2^(alpha - e - 1) <= c | |
17246 // | |
17247 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as | |
17248 // | |
17249 // k = ceil( log_10( 2^(alpha - e - 1) ) ) | |
17250 // = ceil( (alpha - e - 1) * log_10(2) ) | |
17251 // | |
17252 // From the paper: | |
17253 // "In theory the result of the procedure could be wrong since c is rounded, | |
17254 // and the computation itself is approximated [...]. In practice, however, | |
17255 // this simple function is sufficient." | |
17256 // | |
17257 // For IEEE double precision floating-point numbers converted into | |
17258 // normalized diyfp's w = f * 2^e, with q = 64, | |
17259 // | |
17260 // e >= -1022 (min IEEE exponent) | |
17261 // -52 (p - 1) | |
17262 // -52 (p - 1, possibly normalize denormal IEEE numbers) | |
17263 // -11 (normalize the diyfp) | |
17264 // = -1137 | |
17265 // | |
17266 // and | |
17267 // | |
17268 // e <= +1023 (max IEEE exponent) | |
17269 // -52 (p - 1) | |
17270 // -11 (normalize the diyfp) | |
17271 // = 960 | |
17272 // | |
17273 // This binary exponent range [-1137,960] results in a decimal exponent | |
17274 // range [-307,324]. One does not need to store a cached power for each | |
17275 // k in this range. For each such k it suffices to find a cached power | |
17276 // such that the exponent of the product lies in [alpha,gamma]. | |
17277 // This implies that the difference of the decimal exponents of adjacent | |
17278 // table entries must be less than or equal to | |
17279 // | |
17280 // floor( (gamma - alpha) * log_10(2) ) = 8. | |
17281 // | |
17282 // (A smaller distance gamma-alpha would require a larger table.) | |
17283 | |
17284 // NB: | |
17285 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. | |
17286 | |
17287 constexpr int kCachedPowersMinDecExp = -300; | |
17288 constexpr int kCachedPowersDecStep = 8; | |
17289 | |
17290 static constexpr std::array<cached_power, 79> kCachedPowers = | |
17291 { | |
17292 { | |
17293 { 0xAB70FE17C79AC6CA, -1060, -300 }, | |
17294 { 0xFF77B1FCBEBCDC4F, -1034, -292 }, | |
17295 { 0xBE5691EF416BD60C, -1007, -284 }, | |
17296 { 0x8DD01FAD907FFC3C, -980, -276 }, | |
17297 { 0xD3515C2831559A83, -954, -268 }, | |
17298 { 0x9D71AC8FADA6C9B5, -927, -260 }, | |
17299 { 0xEA9C227723EE8BCB, -901, -252 }, | |
17300 { 0xAECC49914078536D, -874, -244 }, | |
17301 { 0x823C12795DB6CE57, -847, -236 }, | |
17302 { 0xC21094364DFB5637, -821, -228 }, | |
17303 { 0x9096EA6F3848984F, -794, -220 }, | |
17304 { 0xD77485CB25823AC7, -768, -212 }, | |
17305 { 0xA086CFCD97BF97F4, -741, -204 }, | |
17306 { 0xEF340A98172AACE5, -715, -196 }, | |
17307 { 0xB23867FB2A35B28E, -688, -188 }, | |
17308 { 0x84C8D4DFD2C63F3B, -661, -180 }, | |
17309 { 0xC5DD44271AD3CDBA, -635, -172 }, | |
17310 { 0x936B9FCEBB25C996, -608, -164 }, | |
17311 { 0xDBAC6C247D62A584, -582, -156 }, | |
17312 { 0xA3AB66580D5FDAF6, -555, -148 }, | |
17313 { 0xF3E2F893DEC3F126, -529, -140 }, | |
17314 { 0xB5B5ADA8AAFF80B8, -502, -132 }, | |
17315 { 0x87625F056C7C4A8B, -475, -124 }, | |
17316 { 0xC9BCFF6034C13053, -449, -116 }, | |
17317 { 0x964E858C91BA2655, -422, -108 }, | |
17318 { 0xDFF9772470297EBD, -396, -100 }, | |
17319 { 0xA6DFBD9FB8E5B88F, -369, -92 }, | |
17320 { 0xF8A95FCF88747D94, -343, -84 }, | |
17321 { 0xB94470938FA89BCF, -316, -76 }, | |
17322 { 0x8A08F0F8BF0F156B, -289, -68 }, | |
17323 { 0xCDB02555653131B6, -263, -60 }, | |
17324 { 0x993FE2C6D07B7FAC, -236, -52 }, | |
17325 { 0xE45C10C42A2B3B06, -210, -44 }, | |
17326 { 0xAA242499697392D3, -183, -36 }, | |
17327 { 0xFD87B5F28300CA0E, -157, -28 }, | |
17328 { 0xBCE5086492111AEB, -130, -20 }, | |
17329 { 0x8CBCCC096F5088CC, -103, -12 }, | |
17330 { 0xD1B71758E219652C, -77, -4 }, | |
17331 { 0x9C40000000000000, -50, 4 }, | |
17332 { 0xE8D4A51000000000, -24, 12 }, | |
17333 { 0xAD78EBC5AC620000, 3, 20 }, | |
17334 { 0x813F3978F8940984, 30, 28 }, | |
17335 { 0xC097CE7BC90715B3, 56, 36 }, | |
17336 { 0x8F7E32CE7BEA5C70, 83, 44 }, | |
17337 { 0xD5D238A4ABE98068, 109, 52 }, | |
17338 { 0x9F4F2726179A2245, 136, 60 }, | |
17339 { 0xED63A231D4C4FB27, 162, 68 }, | |
17340 { 0xB0DE65388CC8ADA8, 189, 76 }, | |
17341 { 0x83C7088E1AAB65DB, 216, 84 }, | |
17342 { 0xC45D1DF942711D9A, 242, 92 }, | |
17343 { 0x924D692CA61BE758, 269, 100 }, | |
17344 { 0xDA01EE641A708DEA, 295, 108 }, | |
17345 { 0xA26DA3999AEF774A, 322, 116 }, | |
17346 { 0xF209787BB47D6B85, 348, 124 }, | |
17347 { 0xB454E4A179DD1877, 375, 132 }, | |
17348 { 0x865B86925B9BC5C2, 402, 140 }, | |
17349 { 0xC83553C5C8965D3D, 428, 148 }, | |
17350 { 0x952AB45CFA97A0B3, 455, 156 }, | |
17351 { 0xDE469FBD99A05FE3, 481, 164 }, | |
17352 { 0xA59BC234DB398C25, 508, 172 }, | |
17353 { 0xF6C69A72A3989F5C, 534, 180 }, | |
17354 { 0xB7DCBF5354E9BECE, 561, 188 }, | |
17355 { 0x88FCF317F22241E2, 588, 196 }, | |
17356 { 0xCC20CE9BD35C78A5, 614, 204 }, | |
17357 { 0x98165AF37B2153DF, 641, 212 }, | |
17358 { 0xE2A0B5DC971F303A, 667, 220 }, | |
17359 { 0xA8D9D1535CE3B396, 694, 228 }, | |
17360 { 0xFB9B7CD9A4A7443C, 720, 236 }, | |
17361 { 0xBB764C4CA7A44410, 747, 244 }, | |
17362 { 0x8BAB8EEFB6409C1A, 774, 252 }, | |
17363 { 0xD01FEF10A657842C, 800, 260 }, | |
17364 { 0x9B10A4E5E9913129, 827, 268 }, | |
17365 { 0xE7109BFBA19C0C9D, 853, 276 }, | |
17366 { 0xAC2820D9623BF429, 880, 284 }, | |
17367 { 0x80444B5E7AA7CF85, 907, 292 }, | |
17368 { 0xBF21E44003ACDD2D, 933, 300 }, | |
17369 { 0x8E679C2F5E44FF8F, 960, 308 }, | |
17370 { 0xD433179D9C8CB841, 986, 316 }, | |
17371 { 0x9E19DB92B4E31BA9, 1013, 324 }, | |
17372 } | |
17373 }; | |
17374 | |
17375 // This computation gives exactly the same results for k as | |
17376 // k = ceil((kAlpha - e - 1) * 0.30102999566398114) | |
17377 // for |e| <= 1500, but doesn't require floating-point operations. | |
17378 // NB: log_10(2) ~= 78913 / 2^18 | |
17379 JSON_ASSERT(e >= -1500); | |
17380 JSON_ASSERT(e <= 1500); | |
17381 const int f = kAlpha - e - 1; | |
17382 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0); | |
17383 | |
17384 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; | |
17385 JSON_ASSERT(index >= 0); | |
17386 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size()); | |
17387 | |
17388 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)]; | |
17389 JSON_ASSERT(kAlpha <= cached.e + e + 64); | |
17390 JSON_ASSERT(kGamma >= cached.e + e + 64); | |
17391 | |
17392 return cached; | |
17393 } | |
17394 | |
17395 /*! | |
17396 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. | |
17397 For n == 0, returns 1 and sets pow10 := 1. | |
17398 */ | |
17399 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) | |
17400 { | |
17401 // LCOV_EXCL_START | |
17402 if (n >= 1000000000) | |
17403 { | |
17404 pow10 = 1000000000; | |
17405 return 10; | |
17406 } | |
17407 // LCOV_EXCL_STOP | |
17408 if (n >= 100000000) | |
17409 { | |
17410 pow10 = 100000000; | |
17411 return 9; | |
17412 } | |
17413 if (n >= 10000000) | |
17414 { | |
17415 pow10 = 10000000; | |
17416 return 8; | |
17417 } | |
17418 if (n >= 1000000) | |
17419 { | |
17420 pow10 = 1000000; | |
17421 return 7; | |
17422 } | |
17423 if (n >= 100000) | |
17424 { | |
17425 pow10 = 100000; | |
17426 return 6; | |
17427 } | |
17428 if (n >= 10000) | |
17429 { | |
17430 pow10 = 10000; | |
17431 return 5; | |
17432 } | |
17433 if (n >= 1000) | |
17434 { | |
17435 pow10 = 1000; | |
17436 return 4; | |
17437 } | |
17438 if (n >= 100) | |
17439 { | |
17440 pow10 = 100; | |
17441 return 3; | |
17442 } | |
17443 if (n >= 10) | |
17444 { | |
17445 pow10 = 10; | |
17446 return 2; | |
17447 } | |
17448 | |
17449 pow10 = 1; | |
17450 return 1; | |
17451 } | |
17452 | |
17453 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, | |
17454 std::uint64_t rest, std::uint64_t ten_k) | |
17455 { | |
17456 JSON_ASSERT(len >= 1); | |
17457 JSON_ASSERT(dist <= delta); | |
17458 JSON_ASSERT(rest <= delta); | |
17459 JSON_ASSERT(ten_k > 0); | |
17460 | |
17461 // <--------------------------- delta ----> | |
17462 // <---- dist ---------> | |
17463 // --------------[------------------+-------------------]-------------- | |
17464 // M- w M+ | |
17465 // | |
17466 // ten_k | |
17467 // <------> | |
17468 // <---- rest ----> | |
17469 // --------------[------------------+----+--------------]-------------- | |
17470 // w V | |
17471 // = buf * 10^k | |
17472 // | |
17473 // ten_k represents a unit-in-the-last-place in the decimal representation | |
17474 // stored in buf. | |
17475 // Decrement buf by ten_k while this takes buf closer to w. | |
17476 | |
17477 // The tests are written in this order to avoid overflow in unsigned | |
17478 // integer arithmetic. | |
17479 | |
17480 while (rest < dist | |
17481 && delta - rest >= ten_k | |
17482 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) | |
17483 { | |
17484 JSON_ASSERT(buf[len - 1] != '0'); | |
17485 buf[len - 1]--; | |
17486 rest += ten_k; | |
17487 } | |
17488 } | |
17489 | |
17490 /*! | |
17491 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. | |
17492 M- and M+ must be normalized and share the same exponent -60 <= e <= -32. | |
17493 */ | |
17494 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, | |
17495 diyfp M_minus, diyfp w, diyfp M_plus) | |
17496 { | |
17497 static_assert(kAlpha >= -60, "internal error"); | |
17498 static_assert(kGamma <= -32, "internal error"); | |
17499 | |
17500 // Generates the digits (and the exponent) of a decimal floating-point | |
17501 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's | |
17502 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. | |
17503 // | |
17504 // <--------------------------- delta ----> | |
17505 // <---- dist ---------> | |
17506 // --------------[------------------+-------------------]-------------- | |
17507 // M- w M+ | |
17508 // | |
17509 // Grisu2 generates the digits of M+ from left to right and stops as soon as | |
17510 // V is in [M-,M+]. | |
17511 | |
17512 JSON_ASSERT(M_plus.e >= kAlpha); | |
17513 JSON_ASSERT(M_plus.e <= kGamma); | |
17514 | |
17515 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) | |
17516 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) | |
17517 | |
17518 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): | |
17519 // | |
17520 // M+ = f * 2^e | |
17521 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e | |
17522 // = ((p1 ) * 2^-e + (p2 )) * 2^e | |
17523 // = p1 + p2 * 2^e | |
17524 | |
17525 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); | |
17526 | |
17527 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) | |
17528 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e | |
17529 | |
17530 // 1) | |
17531 // | |
17532 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] | |
17533 | |
17534 JSON_ASSERT(p1 > 0); | |
17535 | |
17536 std::uint32_t pow10{}; | |
17537 const int k = find_largest_pow10(p1, pow10); | |
17538 | |
17539 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) | |
17540 // | |
17541 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) | |
17542 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) | |
17543 // | |
17544 // M+ = p1 + p2 * 2^e | |
17545 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e | |
17546 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e | |
17547 // = d[k-1] * 10^(k-1) + ( rest) * 2^e | |
17548 // | |
17549 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) | |
17550 // | |
17551 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] | |
17552 // | |
17553 // but stop as soon as | |
17554 // | |
17555 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e | |
17556 | |
17557 int n = k; | |
17558 while (n > 0) | |
17559 { | |
17560 // Invariants: | |
17561 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) | |
17562 // pow10 = 10^(n-1) <= p1 < 10^n | |
17563 // | |
17564 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) | |
17565 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) | |
17566 // | |
17567 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e | |
17568 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) | |
17569 // | |
17570 JSON_ASSERT(d <= 9); | |
17571 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d | |
17572 // | |
17573 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) | |
17574 // | |
17575 p1 = r; | |
17576 n--; | |
17577 // | |
17578 // M+ = buffer * 10^n + (p1 + p2 * 2^e) | |
17579 // pow10 = 10^n | |
17580 // | |
17581 | |
17582 // Now check if enough digits have been generated. | |
17583 // Compute | |
17584 // | |
17585 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e | |
17586 // | |
17587 // Note: | |
17588 // Since rest and delta share the same exponent e, it suffices to | |
17589 // compare the significands. | |
17590 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; | |
17591 if (rest <= delta) | |
17592 { | |
17593 // V = buffer * 10^n, with M- <= V <= M+. | |
17594 | |
17595 decimal_exponent += n; | |
17596 | |
17597 // We may now just stop. But instead look if the buffer could be | |
17598 // decremented to bring V closer to w. | |
17599 // | |
17600 // pow10 = 10^n is now 1 ulp in the decimal representation V. | |
17601 // The rounding procedure works with diyfp's with an implicit | |
17602 // exponent of e. | |
17603 // | |
17604 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e | |
17605 // | |
17606 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; | |
17607 grisu2_round(buffer, length, dist, delta, rest, ten_n); | |
17608 | |
17609 return; | |
17610 } | |
17611 | |
17612 pow10 /= 10; | |
17613 // | |
17614 // pow10 = 10^(n-1) <= p1 < 10^n | |
17615 // Invariants restored. | |
17616 } | |
17617 | |
17618 // 2) | |
17619 // | |
17620 // The digits of the integral part have been generated: | |
17621 // | |
17622 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e | |
17623 // = buffer + p2 * 2^e | |
17624 // | |
17625 // Now generate the digits of the fractional part p2 * 2^e. | |
17626 // | |
17627 // Note: | |
17628 // No decimal point is generated: the exponent is adjusted instead. | |
17629 // | |
17630 // p2 actually represents the fraction | |
17631 // | |
17632 // p2 * 2^e | |
17633 // = p2 / 2^-e | |
17634 // = d[-1] / 10^1 + d[-2] / 10^2 + ... | |
17635 // | |
17636 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) | |
17637 // | |
17638 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m | |
17639 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) | |
17640 // | |
17641 // using | |
17642 // | |
17643 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) | |
17644 // = ( d) * 2^-e + ( r) | |
17645 // | |
17646 // or | |
17647 // 10^m * p2 * 2^e = d + r * 2^e | |
17648 // | |
17649 // i.e. | |
17650 // | |
17651 // M+ = buffer + p2 * 2^e | |
17652 // = buffer + 10^-m * (d + r * 2^e) | |
17653 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e | |
17654 // | |
17655 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e | |
17656 | |
17657 JSON_ASSERT(p2 > delta); | |
17658 | |
17659 int m = 0; | |
17660 for (;;) | |
17661 { | |
17662 // Invariant: | |
17663 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e | |
17664 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e | |
17665 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e | |
17666 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e | |
17667 // | |
17668 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10); | |
17669 p2 *= 10; | |
17670 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e | |
17671 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e | |
17672 // | |
17673 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e | |
17674 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) | |
17675 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e | |
17676 // | |
17677 JSON_ASSERT(d <= 9); | |
17678 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d | |
17679 // | |
17680 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e | |
17681 // | |
17682 p2 = r; | |
17683 m++; | |
17684 // | |
17685 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e | |
17686 // Invariant restored. | |
17687 | |
17688 // Check if enough digits have been generated. | |
17689 // | |
17690 // 10^-m * p2 * 2^e <= delta * 2^e | |
17691 // p2 * 2^e <= 10^m * delta * 2^e | |
17692 // p2 <= 10^m * delta | |
17693 delta *= 10; | |
17694 dist *= 10; | |
17695 if (p2 <= delta) | |
17696 { | |
17697 break; | |
17698 } | |
17699 } | |
17700 | |
17701 // V = buffer * 10^-m, with M- <= V <= M+. | |
17702 | |
17703 decimal_exponent -= m; | |
17704 | |
17705 // 1 ulp in the decimal representation is now 10^-m. | |
17706 // Since delta and dist are now scaled by 10^m, we need to do the | |
17707 // same with ulp in order to keep the units in sync. | |
17708 // | |
17709 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e | |
17710 // | |
17711 const std::uint64_t ten_m = one.f; | |
17712 grisu2_round(buffer, length, dist, delta, p2, ten_m); | |
17713 | |
17714 // By construction this algorithm generates the shortest possible decimal | |
17715 // number (Loitsch, Theorem 6.2) which rounds back to w. | |
17716 // For an input number of precision p, at least | |
17717 // | |
17718 // N = 1 + ceil(p * log_10(2)) | |
17719 // | |
17720 // decimal digits are sufficient to identify all binary floating-point | |
17721 // numbers (Matula, "In-and-Out conversions"). | |
17722 // This implies that the algorithm does not produce more than N decimal | |
17723 // digits. | |
17724 // | |
17725 // N = 17 for p = 53 (IEEE double precision) | |
17726 // N = 9 for p = 24 (IEEE single precision) | |
17727 } | |
17728 | |
17729 /*! | |
17730 v = buf * 10^decimal_exponent | |
17731 len is the length of the buffer (number of decimal digits) | |
17732 The buffer must be large enough, i.e. >= max_digits10. | |
17733 */ | |
17734 JSON_HEDLEY_NON_NULL(1) | |
17735 inline void grisu2(char* buf, int& len, int& decimal_exponent, | |
17736 diyfp m_minus, diyfp v, diyfp m_plus) | |
17737 { | |
17738 JSON_ASSERT(m_plus.e == m_minus.e); | |
17739 JSON_ASSERT(m_plus.e == v.e); | |
17740 | |
17741 // --------(-----------------------+-----------------------)-------- (A) | |
17742 // m- v m+ | |
17743 // | |
17744 // --------------------(-----------+-----------------------)-------- (B) | |
17745 // m- v m+ | |
17746 // | |
17747 // First scale v (and m- and m+) such that the exponent is in the range | |
17748 // [alpha, gamma]. | |
17749 | |
17750 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); | |
17751 | |
17752 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k | |
17753 | |
17754 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] | |
17755 const diyfp w = diyfp::mul(v, c_minus_k); | |
17756 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); | |
17757 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); | |
17758 | |
17759 // ----(---+---)---------------(---+---)---------------(---+---)---- | |
17760 // w- w w+ | |
17761 // = c*m- = c*v = c*m+ | |
17762 // | |
17763 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and | |
17764 // w+ are now off by a small amount. | |
17765 // In fact: | |
17766 // | |
17767 // w - v * 10^k < 1 ulp | |
17768 // | |
17769 // To account for this inaccuracy, add resp. subtract 1 ulp. | |
17770 // | |
17771 // --------+---[---------------(---+---)---------------]---+-------- | |
17772 // w- M- w M+ w+ | |
17773 // | |
17774 // Now any number in [M-, M+] (bounds included) will round to w when input, | |
17775 // regardless of how the input rounding algorithm breaks ties. | |
17776 // | |
17777 // And digit_gen generates the shortest possible such number in [M-, M+]. | |
17778 // Note that this does not mean that Grisu2 always generates the shortest | |
17779 // possible number in the interval (m-, m+). | |
17780 const diyfp M_minus(w_minus.f + 1, w_minus.e); | |
17781 const diyfp M_plus (w_plus.f - 1, w_plus.e ); | |
17782 | |
17783 decimal_exponent = -cached.k; // = -(-k) = k | |
17784 | |
17785 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); | |
17786 } | |
17787 | |
17788 /*! | |
17789 v = buf * 10^decimal_exponent | |
17790 len is the length of the buffer (number of decimal digits) | |
17791 The buffer must be large enough, i.e. >= max_digits10. | |
17792 */ | |
17793 template<typename FloatType> | |
17794 JSON_HEDLEY_NON_NULL(1) | |
17795 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) | |
17796 { | |
17797 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, | |
17798 "internal error: not enough precision"); | |
17799 | |
17800 JSON_ASSERT(std::isfinite(value)); | |
17801 JSON_ASSERT(value > 0); | |
17802 | |
17803 // If the neighbors (and boundaries) of 'value' are always computed for double-precision | |
17804 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting | |
17805 // decimal representations are not exactly "short". | |
17806 // | |
17807 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) | |
17808 // says "value is converted to a string as if by std::sprintf in the default ("C") locale" | |
17809 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' | |
17810 // does. | |
17811 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the | |
17812 // representation using the corresponding std::from_chars function recovers value exactly". That | |
17813 // indicates that single precision floating-point numbers should be recovered using | |
17814 // 'std::strtof'. | |
17815 // | |
17816 // NB: If the neighbors are computed for single-precision numbers, there is a single float | |
17817 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision | |
17818 // value is off by 1 ulp. | |
17819 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) | |
17820 const boundaries w = compute_boundaries(static_cast<double>(value)); | |
17821 #else | |
17822 const boundaries w = compute_boundaries(value); | |
17823 #endif | |
17824 | |
17825 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); | |
17826 } | |
17827 | |
17828 /*! | |
17829 @brief appends a decimal representation of e to buf | |
17830 @return a pointer to the element following the exponent. | |
17831 @pre -1000 < e < 1000 | |
17832 */ | |
17833 JSON_HEDLEY_NON_NULL(1) | |
17834 JSON_HEDLEY_RETURNS_NON_NULL | |
17835 inline char* append_exponent(char* buf, int e) | |
17836 { | |
17837 JSON_ASSERT(e > -1000); | |
17838 JSON_ASSERT(e < 1000); | |
17839 | |
17840 if (e < 0) | |
17841 { | |
17842 e = -e; | |
17843 *buf++ = '-'; | |
17844 } | |
17845 else | |
17846 { | |
17847 *buf++ = '+'; | |
17848 } | |
17849 | |
17850 auto k = static_cast<std::uint32_t>(e); | |
17851 if (k < 10) | |
17852 { | |
17853 // Always print at least two digits in the exponent. | |
17854 // This is for compatibility with printf("%g"). | |
17855 *buf++ = '0'; | |
17856 *buf++ = static_cast<char>('0' + k); | |
17857 } | |
17858 else if (k < 100) | |
17859 { | |
17860 *buf++ = static_cast<char>('0' + k / 10); | |
17861 k %= 10; | |
17862 *buf++ = static_cast<char>('0' + k); | |
17863 } | |
17864 else | |
17865 { | |
17866 *buf++ = static_cast<char>('0' + k / 100); | |
17867 k %= 100; | |
17868 *buf++ = static_cast<char>('0' + k / 10); | |
17869 k %= 10; | |
17870 *buf++ = static_cast<char>('0' + k); | |
17871 } | |
17872 | |
17873 return buf; | |
17874 } | |
17875 | |
17876 /*! | |
17877 @brief prettify v = buf * 10^decimal_exponent | |
17878 | |
17879 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point | |
17880 notation. Otherwise it will be printed in exponential notation. | |
17881 | |
17882 @pre min_exp < 0 | |
17883 @pre max_exp > 0 | |
17884 */ | |
17885 JSON_HEDLEY_NON_NULL(1) | |
17886 JSON_HEDLEY_RETURNS_NON_NULL | |
17887 inline char* format_buffer(char* buf, int len, int decimal_exponent, | |
17888 int min_exp, int max_exp) | |
17889 { | |
17890 JSON_ASSERT(min_exp < 0); | |
17891 JSON_ASSERT(max_exp > 0); | |
17892 | |
17893 const int k = len; | |
17894 const int n = len + decimal_exponent; | |
17895 | |
17896 // v = buf * 10^(n-k) | |
17897 // k is the length of the buffer (number of decimal digits) | |
17898 // n is the position of the decimal point relative to the start of the buffer. | |
17899 | |
17900 if (k <= n && n <= max_exp) | |
17901 { | |
17902 // digits[000] | |
17903 // len <= max_exp + 2 | |
17904 | |
17905 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k)); | |
17906 // Make it look like a floating-point number (#362, #378) | |
17907 buf[n + 0] = '.'; | |
17908 buf[n + 1] = '0'; | |
17909 return buf + (static_cast<size_t>(n) + 2); | |
17910 } | |
17911 | |
17912 if (0 < n && n <= max_exp) | |
17913 { | |
17914 // dig.its | |
17915 // len <= max_digits10 + 1 | |
17916 | |
17917 JSON_ASSERT(k > n); | |
17918 | |
17919 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n)); | |
17920 buf[n] = '.'; | |
17921 return buf + (static_cast<size_t>(k) + 1U); | |
17922 } | |
17923 | |
17924 if (min_exp < n && n <= 0) | |
17925 { | |
17926 // 0.[000]digits | |
17927 // len <= 2 + (-min_exp - 1) + max_digits10 | |
17928 | |
17929 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k)); | |
17930 buf[0] = '0'; | |
17931 buf[1] = '.'; | |
17932 std::memset(buf + 2, '0', static_cast<size_t>(-n)); | |
17933 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k)); | |
17934 } | |
17935 | |
17936 if (k == 1) | |
17937 { | |
17938 // dE+123 | |
17939 // len <= 1 + 5 | |
17940 | |
17941 buf += 1; | |
17942 } | |
17943 else | |
17944 { | |
17945 // d.igitsE+123 | |
17946 // len <= max_digits10 + 1 + 5 | |
17947 | |
17948 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1); | |
17949 buf[1] = '.'; | |
17950 buf += 1 + static_cast<size_t>(k); | |
17951 } | |
17952 | |
17953 *buf++ = 'e'; | |
17954 return append_exponent(buf, n - 1); | |
17955 } | |
17956 | |
17957 } // namespace dtoa_impl | |
17958 | |
17959 /*! | |
17960 @brief generates a decimal representation of the floating-point number value in [first, last). | |
17961 | |
17962 The format of the resulting decimal representation is similar to printf's %g | |
17963 format. Returns an iterator pointing past-the-end of the decimal representation. | |
17964 | |
17965 @note The input number must be finite, i.e. NaN's and Inf's are not supported. | |
17966 @note The buffer must be large enough. | |
17967 @note The result is NOT null-terminated. | |
17968 */ | |
17969 template<typename FloatType> | |
17970 JSON_HEDLEY_NON_NULL(1, 2) | |
17971 JSON_HEDLEY_RETURNS_NON_NULL | |
17972 char* to_chars(char* first, const char* last, FloatType value) | |
17973 { | |
17974 static_cast<void>(last); // maybe unused - fix warning | |
17975 JSON_ASSERT(std::isfinite(value)); | |
17976 | |
17977 // Use signbit(value) instead of (value < 0) since signbit works for -0. | |
17978 if (std::signbit(value)) | |
17979 { | |
17980 value = -value; | |
17981 *first++ = '-'; | |
17982 } | |
17983 | |
17984 #ifdef __GNUC__ | |
17985 #pragma GCC diagnostic push | |
17986 #pragma GCC diagnostic ignored "-Wfloat-equal" | |
17987 #endif | |
17988 if (value == 0) // +-0 | |
17989 { | |
17990 *first++ = '0'; | |
17991 // Make it look like a floating-point number (#362, #378) | |
17992 *first++ = '.'; | |
17993 *first++ = '0'; | |
17994 return first; | |
17995 } | |
17996 #ifdef __GNUC__ | |
17997 #pragma GCC diagnostic pop | |
17998 #endif | |
17999 | |
18000 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10); | |
18001 | |
18002 // Compute v = buffer * 10^decimal_exponent. | |
18003 // The decimal digits are stored in the buffer, which needs to be interpreted | |
18004 // as an unsigned decimal integer. | |
18005 // len is the length of the buffer, i.e. the number of decimal digits. | |
18006 int len = 0; | |
18007 int decimal_exponent = 0; | |
18008 dtoa_impl::grisu2(first, len, decimal_exponent, value); | |
18009 | |
18010 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10); | |
18011 | |
18012 // Format the buffer like printf("%.*g", prec, value) | |
18013 constexpr int kMinExp = -4; | |
18014 // Use digits10 here to increase compatibility with version 2. | |
18015 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; | |
18016 | |
18017 JSON_ASSERT(last - first >= kMaxExp + 2); | |
18018 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); | |
18019 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); | |
18020 | |
18021 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); | |
18022 } | |
18023 | |
18024 } // namespace detail | |
18025 NLOHMANN_JSON_NAMESPACE_END | |
18026 | |
18027 // #include <nlohmann/detail/exceptions.hpp> | |
18028 | |
18029 // #include <nlohmann/detail/macro_scope.hpp> | |
18030 | |
18031 // #include <nlohmann/detail/meta/cpp_future.hpp> | |
18032 | |
18033 // #include <nlohmann/detail/output/binary_writer.hpp> | |
18034 | |
18035 // #include <nlohmann/detail/output/output_adapters.hpp> | |
18036 | |
18037 // #include <nlohmann/detail/string_concat.hpp> | |
18038 | |
18039 // #include <nlohmann/detail/value_t.hpp> | |
18040 | |
18041 | |
18042 NLOHMANN_JSON_NAMESPACE_BEGIN | |
18043 namespace detail | |
18044 { | |
18045 | |
18046 /////////////////// | |
18047 // serialization // | |
18048 /////////////////// | |
18049 | |
18050 /// how to treat decoding errors | |
18051 enum class error_handler_t | |
18052 { | |
18053 strict, ///< throw a type_error exception in case of invalid UTF-8 | |
18054 replace, ///< replace invalid UTF-8 sequences with U+FFFD | |
18055 ignore ///< ignore invalid UTF-8 sequences | |
18056 }; | |
18057 | |
18058 template<typename BasicJsonType> | |
18059 class serializer | |
18060 { | |
18061 using string_t = typename BasicJsonType::string_t; | |
18062 using number_float_t = typename BasicJsonType::number_float_t; | |
18063 using number_integer_t = typename BasicJsonType::number_integer_t; | |
18064 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
18065 using binary_char_t = typename BasicJsonType::binary_t::value_type; | |
18066 static constexpr std::uint8_t UTF8_ACCEPT = 0; | |
18067 static constexpr std::uint8_t UTF8_REJECT = 1; | |
18068 | |
18069 public: | |
18070 /*! | |
18071 @param[in] s output stream to serialize to | |
18072 @param[in] ichar indentation character to use | |
18073 @param[in] error_handler_ how to react on decoding errors | |
18074 */ | |
18075 serializer(output_adapter_t<char> s, const char ichar, | |
18076 error_handler_t error_handler_ = error_handler_t::strict) | |
18077 : o(std::move(s)) | |
18078 , loc(std::localeconv()) | |
18079 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) | |
18080 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) | |
18081 , indent_char(ichar) | |
18082 , indent_string(512, indent_char) | |
18083 , error_handler(error_handler_) | |
18084 {} | |
18085 | |
18086 // delete because of pointer members | |
18087 serializer(const serializer&) = delete; | |
18088 serializer& operator=(const serializer&) = delete; | |
18089 serializer(serializer&&) = delete; | |
18090 serializer& operator=(serializer&&) = delete; | |
18091 ~serializer() = default; | |
18092 | |
18093 /*! | |
18094 @brief internal implementation of the serialization function | |
18095 | |
18096 This function is called by the public member function dump and organizes | |
18097 the serialization internally. The indentation level is propagated as | |
18098 additional parameter. In case of arrays and objects, the function is | |
18099 called recursively. | |
18100 | |
18101 - strings and object keys are escaped using `escape_string()` | |
18102 - integer numbers are converted implicitly via `operator<<` | |
18103 - floating-point numbers are converted to a string using `"%g"` format | |
18104 - binary values are serialized as objects containing the subtype and the | |
18105 byte array | |
18106 | |
18107 @param[in] val value to serialize | |
18108 @param[in] pretty_print whether the output shall be pretty-printed | |
18109 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters | |
18110 in the output are escaped with `\uXXXX` sequences, and the result consists | |
18111 of ASCII characters only. | |
18112 @param[in] indent_step the indent level | |
18113 @param[in] current_indent the current indent level (only used internally) | |
18114 */ | |
18115 void dump(const BasicJsonType& val, | |
18116 const bool pretty_print, | |
18117 const bool ensure_ascii, | |
18118 const unsigned int indent_step, | |
18119 const unsigned int current_indent = 0) | |
18120 { | |
18121 switch (val.m_data.m_type) | |
18122 { | |
18123 case value_t::object: | |
18124 { | |
18125 if (val.m_data.m_value.object->empty()) | |
18126 { | |
18127 o->write_characters("{}", 2); | |
18128 return; | |
18129 } | |
18130 | |
18131 if (pretty_print) | |
18132 { | |
18133 o->write_characters("{\n", 2); | |
18134 | |
18135 // variable to hold indentation for recursive calls | |
18136 const auto new_indent = current_indent + indent_step; | |
18137 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | |
18138 { | |
18139 indent_string.resize(indent_string.size() * 2, ' '); | |
18140 } | |
18141 | |
18142 // first n-1 elements | |
18143 auto i = val.m_data.m_value.object->cbegin(); | |
18144 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) | |
18145 { | |
18146 o->write_characters(indent_string.c_str(), new_indent); | |
18147 o->write_character('\"'); | |
18148 dump_escaped(i->first, ensure_ascii); | |
18149 o->write_characters("\": ", 3); | |
18150 dump(i->second, true, ensure_ascii, indent_step, new_indent); | |
18151 o->write_characters(",\n", 2); | |
18152 } | |
18153 | |
18154 // last element | |
18155 JSON_ASSERT(i != val.m_data.m_value.object->cend()); | |
18156 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); | |
18157 o->write_characters(indent_string.c_str(), new_indent); | |
18158 o->write_character('\"'); | |
18159 dump_escaped(i->first, ensure_ascii); | |
18160 o->write_characters("\": ", 3); | |
18161 dump(i->second, true, ensure_ascii, indent_step, new_indent); | |
18162 | |
18163 o->write_character('\n'); | |
18164 o->write_characters(indent_string.c_str(), current_indent); | |
18165 o->write_character('}'); | |
18166 } | |
18167 else | |
18168 { | |
18169 o->write_character('{'); | |
18170 | |
18171 // first n-1 elements | |
18172 auto i = val.m_data.m_value.object->cbegin(); | |
18173 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) | |
18174 { | |
18175 o->write_character('\"'); | |
18176 dump_escaped(i->first, ensure_ascii); | |
18177 o->write_characters("\":", 2); | |
18178 dump(i->second, false, ensure_ascii, indent_step, current_indent); | |
18179 o->write_character(','); | |
18180 } | |
18181 | |
18182 // last element | |
18183 JSON_ASSERT(i != val.m_data.m_value.object->cend()); | |
18184 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); | |
18185 o->write_character('\"'); | |
18186 dump_escaped(i->first, ensure_ascii); | |
18187 o->write_characters("\":", 2); | |
18188 dump(i->second, false, ensure_ascii, indent_step, current_indent); | |
18189 | |
18190 o->write_character('}'); | |
18191 } | |
18192 | |
18193 return; | |
18194 } | |
18195 | |
18196 case value_t::array: | |
18197 { | |
18198 if (val.m_data.m_value.array->empty()) | |
18199 { | |
18200 o->write_characters("[]", 2); | |
18201 return; | |
18202 } | |
18203 | |
18204 if (pretty_print) | |
18205 { | |
18206 o->write_characters("[\n", 2); | |
18207 | |
18208 // variable to hold indentation for recursive calls | |
18209 const auto new_indent = current_indent + indent_step; | |
18210 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | |
18211 { | |
18212 indent_string.resize(indent_string.size() * 2, ' '); | |
18213 } | |
18214 | |
18215 // first n-1 elements | |
18216 for (auto i = val.m_data.m_value.array->cbegin(); | |
18217 i != val.m_data.m_value.array->cend() - 1; ++i) | |
18218 { | |
18219 o->write_characters(indent_string.c_str(), new_indent); | |
18220 dump(*i, true, ensure_ascii, indent_step, new_indent); | |
18221 o->write_characters(",\n", 2); | |
18222 } | |
18223 | |
18224 // last element | |
18225 JSON_ASSERT(!val.m_data.m_value.array->empty()); | |
18226 o->write_characters(indent_string.c_str(), new_indent); | |
18227 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); | |
18228 | |
18229 o->write_character('\n'); | |
18230 o->write_characters(indent_string.c_str(), current_indent); | |
18231 o->write_character(']'); | |
18232 } | |
18233 else | |
18234 { | |
18235 o->write_character('['); | |
18236 | |
18237 // first n-1 elements | |
18238 for (auto i = val.m_data.m_value.array->cbegin(); | |
18239 i != val.m_data.m_value.array->cend() - 1; ++i) | |
18240 { | |
18241 dump(*i, false, ensure_ascii, indent_step, current_indent); | |
18242 o->write_character(','); | |
18243 } | |
18244 | |
18245 // last element | |
18246 JSON_ASSERT(!val.m_data.m_value.array->empty()); | |
18247 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); | |
18248 | |
18249 o->write_character(']'); | |
18250 } | |
18251 | |
18252 return; | |
18253 } | |
18254 | |
18255 case value_t::string: | |
18256 { | |
18257 o->write_character('\"'); | |
18258 dump_escaped(*val.m_data.m_value.string, ensure_ascii); | |
18259 o->write_character('\"'); | |
18260 return; | |
18261 } | |
18262 | |
18263 case value_t::binary: | |
18264 { | |
18265 if (pretty_print) | |
18266 { | |
18267 o->write_characters("{\n", 2); | |
18268 | |
18269 // variable to hold indentation for recursive calls | |
18270 const auto new_indent = current_indent + indent_step; | |
18271 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) | |
18272 { | |
18273 indent_string.resize(indent_string.size() * 2, ' '); | |
18274 } | |
18275 | |
18276 o->write_characters(indent_string.c_str(), new_indent); | |
18277 | |
18278 o->write_characters("\"bytes\": [", 10); | |
18279 | |
18280 if (!val.m_data.m_value.binary->empty()) | |
18281 { | |
18282 for (auto i = val.m_data.m_value.binary->cbegin(); | |
18283 i != val.m_data.m_value.binary->cend() - 1; ++i) | |
18284 { | |
18285 dump_integer(*i); | |
18286 o->write_characters(", ", 2); | |
18287 } | |
18288 dump_integer(val.m_data.m_value.binary->back()); | |
18289 } | |
18290 | |
18291 o->write_characters("],\n", 3); | |
18292 o->write_characters(indent_string.c_str(), new_indent); | |
18293 | |
18294 o->write_characters("\"subtype\": ", 11); | |
18295 if (val.m_data.m_value.binary->has_subtype()) | |
18296 { | |
18297 dump_integer(val.m_data.m_value.binary->subtype()); | |
18298 } | |
18299 else | |
18300 { | |
18301 o->write_characters("null", 4); | |
18302 } | |
18303 o->write_character('\n'); | |
18304 o->write_characters(indent_string.c_str(), current_indent); | |
18305 o->write_character('}'); | |
18306 } | |
18307 else | |
18308 { | |
18309 o->write_characters("{\"bytes\":[", 10); | |
18310 | |
18311 if (!val.m_data.m_value.binary->empty()) | |
18312 { | |
18313 for (auto i = val.m_data.m_value.binary->cbegin(); | |
18314 i != val.m_data.m_value.binary->cend() - 1; ++i) | |
18315 { | |
18316 dump_integer(*i); | |
18317 o->write_character(','); | |
18318 } | |
18319 dump_integer(val.m_data.m_value.binary->back()); | |
18320 } | |
18321 | |
18322 o->write_characters("],\"subtype\":", 12); | |
18323 if (val.m_data.m_value.binary->has_subtype()) | |
18324 { | |
18325 dump_integer(val.m_data.m_value.binary->subtype()); | |
18326 o->write_character('}'); | |
18327 } | |
18328 else | |
18329 { | |
18330 o->write_characters("null}", 5); | |
18331 } | |
18332 } | |
18333 return; | |
18334 } | |
18335 | |
18336 case value_t::boolean: | |
18337 { | |
18338 if (val.m_data.m_value.boolean) | |
18339 { | |
18340 o->write_characters("true", 4); | |
18341 } | |
18342 else | |
18343 { | |
18344 o->write_characters("false", 5); | |
18345 } | |
18346 return; | |
18347 } | |
18348 | |
18349 case value_t::number_integer: | |
18350 { | |
18351 dump_integer(val.m_data.m_value.number_integer); | |
18352 return; | |
18353 } | |
18354 | |
18355 case value_t::number_unsigned: | |
18356 { | |
18357 dump_integer(val.m_data.m_value.number_unsigned); | |
18358 return; | |
18359 } | |
18360 | |
18361 case value_t::number_float: | |
18362 { | |
18363 dump_float(val.m_data.m_value.number_float); | |
18364 return; | |
18365 } | |
18366 | |
18367 case value_t::discarded: | |
18368 { | |
18369 o->write_characters("<discarded>", 11); | |
18370 return; | |
18371 } | |
18372 | |
18373 case value_t::null: | |
18374 { | |
18375 o->write_characters("null", 4); | |
18376 return; | |
18377 } | |
18378 | |
18379 default: // LCOV_EXCL_LINE | |
18380 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
18381 } | |
18382 } | |
18383 | |
18384 JSON_PRIVATE_UNLESS_TESTED: | |
18385 /*! | |
18386 @brief dump escaped string | |
18387 | |
18388 Escape a string by replacing certain special characters by a sequence of an | |
18389 escape character (backslash) and another character and other control | |
18390 characters by a sequence of "\u" followed by a four-digit hex | |
18391 representation. The escaped string is written to output stream @a o. | |
18392 | |
18393 @param[in] s the string to escape | |
18394 @param[in] ensure_ascii whether to escape non-ASCII characters with | |
18395 \uXXXX sequences | |
18396 | |
18397 @complexity Linear in the length of string @a s. | |
18398 */ | |
18399 void dump_escaped(const string_t& s, const bool ensure_ascii) | |
18400 { | |
18401 std::uint32_t codepoint{}; | |
18402 std::uint8_t state = UTF8_ACCEPT; | |
18403 std::size_t bytes = 0; // number of bytes written to string_buffer | |
18404 | |
18405 // number of bytes written at the point of the last valid byte | |
18406 std::size_t bytes_after_last_accept = 0; | |
18407 std::size_t undumped_chars = 0; | |
18408 | |
18409 for (std::size_t i = 0; i < s.size(); ++i) | |
18410 { | |
18411 const auto byte = static_cast<std::uint8_t>(s[i]); | |
18412 | |
18413 switch (decode(state, codepoint, byte)) | |
18414 { | |
18415 case UTF8_ACCEPT: // decode found a new code point | |
18416 { | |
18417 switch (codepoint) | |
18418 { | |
18419 case 0x08: // backspace | |
18420 { | |
18421 string_buffer[bytes++] = '\\'; | |
18422 string_buffer[bytes++] = 'b'; | |
18423 break; | |
18424 } | |
18425 | |
18426 case 0x09: // horizontal tab | |
18427 { | |
18428 string_buffer[bytes++] = '\\'; | |
18429 string_buffer[bytes++] = 't'; | |
18430 break; | |
18431 } | |
18432 | |
18433 case 0x0A: // newline | |
18434 { | |
18435 string_buffer[bytes++] = '\\'; | |
18436 string_buffer[bytes++] = 'n'; | |
18437 break; | |
18438 } | |
18439 | |
18440 case 0x0C: // formfeed | |
18441 { | |
18442 string_buffer[bytes++] = '\\'; | |
18443 string_buffer[bytes++] = 'f'; | |
18444 break; | |
18445 } | |
18446 | |
18447 case 0x0D: // carriage return | |
18448 { | |
18449 string_buffer[bytes++] = '\\'; | |
18450 string_buffer[bytes++] = 'r'; | |
18451 break; | |
18452 } | |
18453 | |
18454 case 0x22: // quotation mark | |
18455 { | |
18456 string_buffer[bytes++] = '\\'; | |
18457 string_buffer[bytes++] = '\"'; | |
18458 break; | |
18459 } | |
18460 | |
18461 case 0x5C: // reverse solidus | |
18462 { | |
18463 string_buffer[bytes++] = '\\'; | |
18464 string_buffer[bytes++] = '\\'; | |
18465 break; | |
18466 } | |
18467 | |
18468 default: | |
18469 { | |
18470 // escape control characters (0x00..0x1F) or, if | |
18471 // ensure_ascii parameter is used, non-ASCII characters | |
18472 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) | |
18473 { | |
18474 if (codepoint <= 0xFFFF) | |
18475 { | |
18476 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
18477 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", | |
18478 static_cast<std::uint16_t>(codepoint))); | |
18479 bytes += 6; | |
18480 } | |
18481 else | |
18482 { | |
18483 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
18484 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", | |
18485 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), | |
18486 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); | |
18487 bytes += 12; | |
18488 } | |
18489 } | |
18490 else | |
18491 { | |
18492 // copy byte to buffer (all previous bytes | |
18493 // been copied have in default case above) | |
18494 string_buffer[bytes++] = s[i]; | |
18495 } | |
18496 break; | |
18497 } | |
18498 } | |
18499 | |
18500 // write buffer and reset index; there must be 13 bytes | |
18501 // left, as this is the maximal number of bytes to be | |
18502 // written ("\uxxxx\uxxxx\0") for one code point | |
18503 if (string_buffer.size() - bytes < 13) | |
18504 { | |
18505 o->write_characters(string_buffer.data(), bytes); | |
18506 bytes = 0; | |
18507 } | |
18508 | |
18509 // remember the byte position of this accept | |
18510 bytes_after_last_accept = bytes; | |
18511 undumped_chars = 0; | |
18512 break; | |
18513 } | |
18514 | |
18515 case UTF8_REJECT: // decode found invalid UTF-8 byte | |
18516 { | |
18517 switch (error_handler) | |
18518 { | |
18519 case error_handler_t::strict: | |
18520 { | |
18521 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); | |
18522 } | |
18523 | |
18524 case error_handler_t::ignore: | |
18525 case error_handler_t::replace: | |
18526 { | |
18527 // in case we saw this character the first time, we | |
18528 // would like to read it again, because the byte | |
18529 // may be OK for itself, but just not OK for the | |
18530 // previous sequence | |
18531 if (undumped_chars > 0) | |
18532 { | |
18533 --i; | |
18534 } | |
18535 | |
18536 // reset length buffer to the last accepted index; | |
18537 // thus removing/ignoring the invalid characters | |
18538 bytes = bytes_after_last_accept; | |
18539 | |
18540 if (error_handler == error_handler_t::replace) | |
18541 { | |
18542 // add a replacement character | |
18543 if (ensure_ascii) | |
18544 { | |
18545 string_buffer[bytes++] = '\\'; | |
18546 string_buffer[bytes++] = 'u'; | |
18547 string_buffer[bytes++] = 'f'; | |
18548 string_buffer[bytes++] = 'f'; | |
18549 string_buffer[bytes++] = 'f'; | |
18550 string_buffer[bytes++] = 'd'; | |
18551 } | |
18552 else | |
18553 { | |
18554 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); | |
18555 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); | |
18556 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); | |
18557 } | |
18558 | |
18559 // write buffer and reset index; there must be 13 bytes | |
18560 // left, as this is the maximal number of bytes to be | |
18561 // written ("\uxxxx\uxxxx\0") for one code point | |
18562 if (string_buffer.size() - bytes < 13) | |
18563 { | |
18564 o->write_characters(string_buffer.data(), bytes); | |
18565 bytes = 0; | |
18566 } | |
18567 | |
18568 bytes_after_last_accept = bytes; | |
18569 } | |
18570 | |
18571 undumped_chars = 0; | |
18572 | |
18573 // continue processing the string | |
18574 state = UTF8_ACCEPT; | |
18575 break; | |
18576 } | |
18577 | |
18578 default: // LCOV_EXCL_LINE | |
18579 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
18580 } | |
18581 break; | |
18582 } | |
18583 | |
18584 default: // decode found yet incomplete multi-byte code point | |
18585 { | |
18586 if (!ensure_ascii) | |
18587 { | |
18588 // code point will not be escaped - copy byte to buffer | |
18589 string_buffer[bytes++] = s[i]; | |
18590 } | |
18591 ++undumped_chars; | |
18592 break; | |
18593 } | |
18594 } | |
18595 } | |
18596 | |
18597 // we finished processing the string | |
18598 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) | |
18599 { | |
18600 // write buffer | |
18601 if (bytes > 0) | |
18602 { | |
18603 o->write_characters(string_buffer.data(), bytes); | |
18604 } | |
18605 } | |
18606 else | |
18607 { | |
18608 // we finish reading, but do not accept: string was incomplete | |
18609 switch (error_handler) | |
18610 { | |
18611 case error_handler_t::strict: | |
18612 { | |
18613 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr)); | |
18614 } | |
18615 | |
18616 case error_handler_t::ignore: | |
18617 { | |
18618 // write all accepted bytes | |
18619 o->write_characters(string_buffer.data(), bytes_after_last_accept); | |
18620 break; | |
18621 } | |
18622 | |
18623 case error_handler_t::replace: | |
18624 { | |
18625 // write all accepted bytes | |
18626 o->write_characters(string_buffer.data(), bytes_after_last_accept); | |
18627 // add a replacement character | |
18628 if (ensure_ascii) | |
18629 { | |
18630 o->write_characters("\\ufffd", 6); | |
18631 } | |
18632 else | |
18633 { | |
18634 o->write_characters("\xEF\xBF\xBD", 3); | |
18635 } | |
18636 break; | |
18637 } | |
18638 | |
18639 default: // LCOV_EXCL_LINE | |
18640 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
18641 } | |
18642 } | |
18643 } | |
18644 | |
18645 private: | |
18646 /*! | |
18647 @brief count digits | |
18648 | |
18649 Count the number of decimal (base 10) digits for an input unsigned integer. | |
18650 | |
18651 @param[in] x unsigned integer number to count its digits | |
18652 @return number of decimal digits | |
18653 */ | |
18654 inline unsigned int count_digits(number_unsigned_t x) noexcept | |
18655 { | |
18656 unsigned int n_digits = 1; | |
18657 for (;;) | |
18658 { | |
18659 if (x < 10) | |
18660 { | |
18661 return n_digits; | |
18662 } | |
18663 if (x < 100) | |
18664 { | |
18665 return n_digits + 1; | |
18666 } | |
18667 if (x < 1000) | |
18668 { | |
18669 return n_digits + 2; | |
18670 } | |
18671 if (x < 10000) | |
18672 { | |
18673 return n_digits + 3; | |
18674 } | |
18675 x = x / 10000u; | |
18676 n_digits += 4; | |
18677 } | |
18678 } | |
18679 | |
18680 /*! | |
18681 * @brief convert a byte to a uppercase hex representation | |
18682 * @param[in] byte byte to represent | |
18683 * @return representation ("00".."FF") | |
18684 */ | |
18685 static std::string hex_bytes(std::uint8_t byte) | |
18686 { | |
18687 std::string result = "FF"; | |
18688 constexpr const char* nibble_to_hex = "0123456789ABCDEF"; | |
18689 result[0] = nibble_to_hex[byte / 16]; | |
18690 result[1] = nibble_to_hex[byte % 16]; | |
18691 return result; | |
18692 } | |
18693 | |
18694 // templates to avoid warnings about useless casts | |
18695 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> | |
18696 bool is_negative_number(NumberType x) | |
18697 { | |
18698 return x < 0; | |
18699 } | |
18700 | |
18701 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > | |
18702 bool is_negative_number(NumberType /*unused*/) | |
18703 { | |
18704 return false; | |
18705 } | |
18706 | |
18707 /*! | |
18708 @brief dump an integer | |
18709 | |
18710 Dump a given integer to output stream @a o. Works internally with | |
18711 @a number_buffer. | |
18712 | |
18713 @param[in] x integer number (signed or unsigned) to dump | |
18714 @tparam NumberType either @a number_integer_t or @a number_unsigned_t | |
18715 */ | |
18716 template < typename NumberType, detail::enable_if_t < | |
18717 std::is_integral<NumberType>::value || | |
18718 std::is_same<NumberType, number_unsigned_t>::value || | |
18719 std::is_same<NumberType, number_integer_t>::value || | |
18720 std::is_same<NumberType, binary_char_t>::value, | |
18721 int > = 0 > | |
18722 void dump_integer(NumberType x) | |
18723 { | |
18724 static constexpr std::array<std::array<char, 2>, 100> digits_to_99 | |
18725 { | |
18726 { | |
18727 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, | |
18728 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, | |
18729 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, | |
18730 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, | |
18731 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, | |
18732 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, | |
18733 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, | |
18734 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, | |
18735 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, | |
18736 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, | |
18737 } | |
18738 }; | |
18739 | |
18740 // special case for "0" | |
18741 if (x == 0) | |
18742 { | |
18743 o->write_character('0'); | |
18744 return; | |
18745 } | |
18746 | |
18747 // use a pointer to fill the buffer | |
18748 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
18749 | |
18750 number_unsigned_t abs_value; | |
18751 | |
18752 unsigned int n_chars{}; | |
18753 | |
18754 if (is_negative_number(x)) | |
18755 { | |
18756 *buffer_ptr = '-'; | |
18757 abs_value = remove_sign(static_cast<number_integer_t>(x)); | |
18758 | |
18759 // account one more byte for the minus sign | |
18760 n_chars = 1 + count_digits(abs_value); | |
18761 } | |
18762 else | |
18763 { | |
18764 abs_value = static_cast<number_unsigned_t>(x); | |
18765 n_chars = count_digits(abs_value); | |
18766 } | |
18767 | |
18768 // spare 1 byte for '\0' | |
18769 JSON_ASSERT(n_chars < number_buffer.size() - 1); | |
18770 | |
18771 // jump to the end to generate the string from backward, | |
18772 // so we later avoid reversing the result | |
18773 buffer_ptr += n_chars; | |
18774 | |
18775 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu | |
18776 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg | |
18777 while (abs_value >= 100) | |
18778 { | |
18779 const auto digits_index = static_cast<unsigned>((abs_value % 100)); | |
18780 abs_value /= 100; | |
18781 *(--buffer_ptr) = digits_to_99[digits_index][1]; | |
18782 *(--buffer_ptr) = digits_to_99[digits_index][0]; | |
18783 } | |
18784 | |
18785 if (abs_value >= 10) | |
18786 { | |
18787 const auto digits_index = static_cast<unsigned>(abs_value); | |
18788 *(--buffer_ptr) = digits_to_99[digits_index][1]; | |
18789 *(--buffer_ptr) = digits_to_99[digits_index][0]; | |
18790 } | |
18791 else | |
18792 { | |
18793 *(--buffer_ptr) = static_cast<char>('0' + abs_value); | |
18794 } | |
18795 | |
18796 o->write_characters(number_buffer.data(), n_chars); | |
18797 } | |
18798 | |
18799 /*! | |
18800 @brief dump a floating-point number | |
18801 | |
18802 Dump a given floating-point number to output stream @a o. Works internally | |
18803 with @a number_buffer. | |
18804 | |
18805 @param[in] x floating-point number to dump | |
18806 */ | |
18807 void dump_float(number_float_t x) | |
18808 { | |
18809 // NaN / inf | |
18810 if (!std::isfinite(x)) | |
18811 { | |
18812 o->write_characters("null", 4); | |
18813 return; | |
18814 } | |
18815 | |
18816 // If number_float_t is an IEEE-754 single or double precision number, | |
18817 // use the Grisu2 algorithm to produce short numbers which are | |
18818 // guaranteed to round-trip, using strtof and strtod, resp. | |
18819 // | |
18820 // NB: The test below works if <long double> == <double>. | |
18821 static constexpr bool is_ieee_single_or_double | |
18822 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) || | |
18823 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024); | |
18824 | |
18825 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); | |
18826 } | |
18827 | |
18828 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) | |
18829 { | |
18830 auto* begin = number_buffer.data(); | |
18831 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); | |
18832 | |
18833 o->write_characters(begin, static_cast<size_t>(end - begin)); | |
18834 } | |
18835 | |
18836 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) | |
18837 { | |
18838 // get number of digits for a float -> text -> float round-trip | |
18839 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; | |
18840 | |
18841 // the actual conversion | |
18842 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | |
18843 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); | |
18844 | |
18845 // negative value indicates an error | |
18846 JSON_ASSERT(len > 0); | |
18847 // check if buffer was large enough | |
18848 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); | |
18849 | |
18850 // erase thousands separator | |
18851 if (thousands_sep != '\0') | |
18852 { | |
18853 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 | |
18854 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); | |
18855 std::fill(end, number_buffer.end(), '\0'); | |
18856 JSON_ASSERT((end - number_buffer.begin()) <= len); | |
18857 len = (end - number_buffer.begin()); | |
18858 } | |
18859 | |
18860 // convert decimal point to '.' | |
18861 if (decimal_point != '\0' && decimal_point != '.') | |
18862 { | |
18863 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 | |
18864 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); | |
18865 if (dec_pos != number_buffer.end()) | |
18866 { | |
18867 *dec_pos = '.'; | |
18868 } | |
18869 } | |
18870 | |
18871 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); | |
18872 | |
18873 // determine if we need to append ".0" | |
18874 const bool value_is_int_like = | |
18875 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, | |
18876 [](char c) | |
18877 { | |
18878 return c == '.' || c == 'e'; | |
18879 }); | |
18880 | |
18881 if (value_is_int_like) | |
18882 { | |
18883 o->write_characters(".0", 2); | |
18884 } | |
18885 } | |
18886 | |
18887 /*! | |
18888 @brief check whether a string is UTF-8 encoded | |
18889 | |
18890 The function checks each byte of a string whether it is UTF-8 encoded. The | |
18891 result of the check is stored in the @a state parameter. The function must | |
18892 be called initially with state 0 (accept). State 1 means the string must | |
18893 be rejected, because the current byte is not allowed. If the string is | |
18894 completely processed, but the state is non-zero, the string ended | |
18895 prematurely; that is, the last byte indicated more bytes should have | |
18896 followed. | |
18897 | |
18898 @param[in,out] state the state of the decoding | |
18899 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) | |
18900 @param[in] byte next byte to decode | |
18901 @return new state | |
18902 | |
18903 @note The function has been edited: a std::array is used. | |
18904 | |
18905 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> | |
18906 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ | |
18907 */ | |
18908 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept | |
18909 { | |
18910 static const std::array<std::uint8_t, 400> utf8d = | |
18911 { | |
18912 { | |
18913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F | |
18914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F | |
18915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F | |
18916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F | |
18917 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F | |
18918 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF | |
18919 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF | |
18920 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF | |
18921 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF | |
18922 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 | |
18923 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 | |
18924 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 | |
18925 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 | |
18926 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 | |
18927 } | |
18928 }; | |
18929 | |
18930 JSON_ASSERT(byte < utf8d.size()); | |
18931 const std::uint8_t type = utf8d[byte]; | |
18932 | |
18933 codep = (state != UTF8_ACCEPT) | |
18934 ? (byte & 0x3fu) | (codep << 6u) | |
18935 : (0xFFu >> type) & (byte); | |
18936 | |
18937 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); | |
18938 JSON_ASSERT(index < utf8d.size()); | |
18939 state = utf8d[index]; | |
18940 return state; | |
18941 } | |
18942 | |
18943 /* | |
18944 * Overload to make the compiler happy while it is instantiating | |
18945 * dump_integer for number_unsigned_t. | |
18946 * Must never be called. | |
18947 */ | |
18948 number_unsigned_t remove_sign(number_unsigned_t x) | |
18949 { | |
18950 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
18951 return x; // LCOV_EXCL_LINE | |
18952 } | |
18953 | |
18954 /* | |
18955 * Helper function for dump_integer | |
18956 * | |
18957 * This function takes a negative signed integer and returns its absolute | |
18958 * value as unsigned integer. The plus/minus shuffling is necessary as we can | |
18959 * not directly remove the sign of an arbitrary signed integer as the | |
18960 * absolute values of INT_MIN and INT_MAX are usually not the same. See | |
18961 * #1708 for details. | |
18962 */ | |
18963 inline number_unsigned_t remove_sign(number_integer_t x) noexcept | |
18964 { | |
18965 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) | |
18966 return static_cast<number_unsigned_t>(-(x + 1)) + 1; | |
18967 } | |
18968 | |
18969 private: | |
18970 /// the output of the serializer | |
18971 output_adapter_t<char> o = nullptr; | |
18972 | |
18973 /// a (hopefully) large enough character buffer | |
18974 std::array<char, 64> number_buffer{{}}; | |
18975 | |
18976 /// the locale | |
18977 const std::lconv* loc = nullptr; | |
18978 /// the locale's thousand separator character | |
18979 const char thousands_sep = '\0'; | |
18980 /// the locale's decimal point character | |
18981 const char decimal_point = '\0'; | |
18982 | |
18983 /// string buffer | |
18984 std::array<char, 512> string_buffer{{}}; | |
18985 | |
18986 /// the indentation character | |
18987 const char indent_char; | |
18988 /// the indentation string | |
18989 string_t indent_string; | |
18990 | |
18991 /// error_handler how to react on decoding errors | |
18992 const error_handler_t error_handler; | |
18993 }; | |
18994 | |
18995 } // namespace detail | |
18996 NLOHMANN_JSON_NAMESPACE_END | |
18997 | |
18998 // #include <nlohmann/detail/value_t.hpp> | |
18999 | |
19000 // #include <nlohmann/json_fwd.hpp> | |
19001 | |
19002 // #include <nlohmann/ordered_map.hpp> | |
19003 // __ _____ _____ _____ | |
19004 // __| | __| | | | JSON for Modern C++ | |
19005 // | | |__ | | | | | | version 3.11.3 | |
19006 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
19007 // | |
19008 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
19009 // SPDX-License-Identifier: MIT | |
19010 | |
19011 | |
19012 | |
19013 #include <functional> // equal_to, less | |
19014 #include <initializer_list> // initializer_list | |
19015 #include <iterator> // input_iterator_tag, iterator_traits | |
19016 #include <memory> // allocator | |
19017 #include <stdexcept> // for out_of_range | |
19018 #include <type_traits> // enable_if, is_convertible | |
19019 #include <utility> // pair | |
19020 #include <vector> // vector | |
19021 | |
19022 // #include <nlohmann/detail/macro_scope.hpp> | |
19023 | |
19024 // #include <nlohmann/detail/meta/type_traits.hpp> | |
19025 | |
19026 | |
19027 NLOHMANN_JSON_NAMESPACE_BEGIN | |
19028 | |
19029 /// ordered_map: a minimal map-like container that preserves insertion order | |
19030 /// for use within nlohmann::basic_json<ordered_map> | |
19031 template <class Key, class T, class IgnoredLess = std::less<Key>, | |
19032 class Allocator = std::allocator<std::pair<const Key, T>>> | |
19033 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> | |
19034 { | |
19035 using key_type = Key; | |
19036 using mapped_type = T; | |
19037 using Container = std::vector<std::pair<const Key, T>, Allocator>; | |
19038 using iterator = typename Container::iterator; | |
19039 using const_iterator = typename Container::const_iterator; | |
19040 using size_type = typename Container::size_type; | |
19041 using value_type = typename Container::value_type; | |
19042 #ifdef JSON_HAS_CPP_14 | |
19043 using key_compare = std::equal_to<>; | |
19044 #else | |
19045 using key_compare = std::equal_to<Key>; | |
19046 #endif | |
19047 | |
19048 // Explicit constructors instead of `using Container::Container` | |
19049 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) | |
19050 ordered_map() noexcept(noexcept(Container())) : Container{} {} | |
19051 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} | |
19052 template <class It> | |
19053 ordered_map(It first, It last, const Allocator& alloc = Allocator()) | |
19054 : Container{first, last, alloc} {} | |
19055 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) | |
19056 : Container{init, alloc} {} | |
19057 | |
19058 std::pair<iterator, bool> emplace(const key_type& key, T&& t) | |
19059 { | |
19060 for (auto it = this->begin(); it != this->end(); ++it) | |
19061 { | |
19062 if (m_compare(it->first, key)) | |
19063 { | |
19064 return {it, false}; | |
19065 } | |
19066 } | |
19067 Container::emplace_back(key, std::forward<T>(t)); | |
19068 return {std::prev(this->end()), true}; | |
19069 } | |
19070 | |
19071 template<class KeyType, detail::enable_if_t< | |
19072 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19073 std::pair<iterator, bool> emplace(KeyType && key, T && t) | |
19074 { | |
19075 for (auto it = this->begin(); it != this->end(); ++it) | |
19076 { | |
19077 if (m_compare(it->first, key)) | |
19078 { | |
19079 return {it, false}; | |
19080 } | |
19081 } | |
19082 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); | |
19083 return {std::prev(this->end()), true}; | |
19084 } | |
19085 | |
19086 T& operator[](const key_type& key) | |
19087 { | |
19088 return emplace(key, T{}).first->second; | |
19089 } | |
19090 | |
19091 template<class KeyType, detail::enable_if_t< | |
19092 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19093 T & operator[](KeyType && key) | |
19094 { | |
19095 return emplace(std::forward<KeyType>(key), T{}).first->second; | |
19096 } | |
19097 | |
19098 const T& operator[](const key_type& key) const | |
19099 { | |
19100 return at(key); | |
19101 } | |
19102 | |
19103 template<class KeyType, detail::enable_if_t< | |
19104 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19105 const T & operator[](KeyType && key) const | |
19106 { | |
19107 return at(std::forward<KeyType>(key)); | |
19108 } | |
19109 | |
19110 T& at(const key_type& key) | |
19111 { | |
19112 for (auto it = this->begin(); it != this->end(); ++it) | |
19113 { | |
19114 if (m_compare(it->first, key)) | |
19115 { | |
19116 return it->second; | |
19117 } | |
19118 } | |
19119 | |
19120 JSON_THROW(std::out_of_range("key not found")); | |
19121 } | |
19122 | |
19123 template<class KeyType, detail::enable_if_t< | |
19124 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19125 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) | |
19126 { | |
19127 for (auto it = this->begin(); it != this->end(); ++it) | |
19128 { | |
19129 if (m_compare(it->first, key)) | |
19130 { | |
19131 return it->second; | |
19132 } | |
19133 } | |
19134 | |
19135 JSON_THROW(std::out_of_range("key not found")); | |
19136 } | |
19137 | |
19138 const T& at(const key_type& key) const | |
19139 { | |
19140 for (auto it = this->begin(); it != this->end(); ++it) | |
19141 { | |
19142 if (m_compare(it->first, key)) | |
19143 { | |
19144 return it->second; | |
19145 } | |
19146 } | |
19147 | |
19148 JSON_THROW(std::out_of_range("key not found")); | |
19149 } | |
19150 | |
19151 template<class KeyType, detail::enable_if_t< | |
19152 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19153 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) | |
19154 { | |
19155 for (auto it = this->begin(); it != this->end(); ++it) | |
19156 { | |
19157 if (m_compare(it->first, key)) | |
19158 { | |
19159 return it->second; | |
19160 } | |
19161 } | |
19162 | |
19163 JSON_THROW(std::out_of_range("key not found")); | |
19164 } | |
19165 | |
19166 size_type erase(const key_type& key) | |
19167 { | |
19168 for (auto it = this->begin(); it != this->end(); ++it) | |
19169 { | |
19170 if (m_compare(it->first, key)) | |
19171 { | |
19172 // Since we cannot move const Keys, re-construct them in place | |
19173 for (auto next = it; ++next != this->end(); ++it) | |
19174 { | |
19175 it->~value_type(); // Destroy but keep allocation | |
19176 new (&*it) value_type{std::move(*next)}; | |
19177 } | |
19178 Container::pop_back(); | |
19179 return 1; | |
19180 } | |
19181 } | |
19182 return 0; | |
19183 } | |
19184 | |
19185 template<class KeyType, detail::enable_if_t< | |
19186 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19187 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) | |
19188 { | |
19189 for (auto it = this->begin(); it != this->end(); ++it) | |
19190 { | |
19191 if (m_compare(it->first, key)) | |
19192 { | |
19193 // Since we cannot move const Keys, re-construct them in place | |
19194 for (auto next = it; ++next != this->end(); ++it) | |
19195 { | |
19196 it->~value_type(); // Destroy but keep allocation | |
19197 new (&*it) value_type{std::move(*next)}; | |
19198 } | |
19199 Container::pop_back(); | |
19200 return 1; | |
19201 } | |
19202 } | |
19203 return 0; | |
19204 } | |
19205 | |
19206 iterator erase(iterator pos) | |
19207 { | |
19208 return erase(pos, std::next(pos)); | |
19209 } | |
19210 | |
19211 iterator erase(iterator first, iterator last) | |
19212 { | |
19213 if (first == last) | |
19214 { | |
19215 return first; | |
19216 } | |
19217 | |
19218 const auto elements_affected = std::distance(first, last); | |
19219 const auto offset = std::distance(Container::begin(), first); | |
19220 | |
19221 // This is the start situation. We need to delete elements_affected | |
19222 // elements (3 in this example: e, f, g), and need to return an | |
19223 // iterator past the last deleted element (h in this example). | |
19224 // Note that offset is the distance from the start of the vector | |
19225 // to first. We will need this later. | |
19226 | |
19227 // [ a, b, c, d, e, f, g, h, i, j ] | |
19228 // ^ ^ | |
19229 // first last | |
19230 | |
19231 // Since we cannot move const Keys, we re-construct them in place. | |
19232 // We start at first and re-construct (viz. copy) the elements from | |
19233 // the back of the vector. Example for first iteration: | |
19234 | |
19235 // ,--------. | |
19236 // v | destroy e and re-construct with h | |
19237 // [ a, b, c, d, e, f, g, h, i, j ] | |
19238 // ^ ^ | |
19239 // it it + elements_affected | |
19240 | |
19241 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) | |
19242 { | |
19243 it->~value_type(); // destroy but keep allocation | |
19244 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it | |
19245 } | |
19246 | |
19247 // [ a, b, c, d, h, i, j, h, i, j ] | |
19248 // ^ ^ | |
19249 // first last | |
19250 | |
19251 // remove the unneeded elements at the end of the vector | |
19252 Container::resize(this->size() - static_cast<size_type>(elements_affected)); | |
19253 | |
19254 // [ a, b, c, d, h, i, j ] | |
19255 // ^ ^ | |
19256 // first last | |
19257 | |
19258 // first is now pointing past the last deleted element, but we cannot | |
19259 // use this iterator, because it may have been invalidated by the | |
19260 // resize call. Instead, we can return begin() + offset. | |
19261 return Container::begin() + offset; | |
19262 } | |
19263 | |
19264 size_type count(const key_type& key) const | |
19265 { | |
19266 for (auto it = this->begin(); it != this->end(); ++it) | |
19267 { | |
19268 if (m_compare(it->first, key)) | |
19269 { | |
19270 return 1; | |
19271 } | |
19272 } | |
19273 return 0; | |
19274 } | |
19275 | |
19276 template<class KeyType, detail::enable_if_t< | |
19277 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19278 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) | |
19279 { | |
19280 for (auto it = this->begin(); it != this->end(); ++it) | |
19281 { | |
19282 if (m_compare(it->first, key)) | |
19283 { | |
19284 return 1; | |
19285 } | |
19286 } | |
19287 return 0; | |
19288 } | |
19289 | |
19290 iterator find(const key_type& key) | |
19291 { | |
19292 for (auto it = this->begin(); it != this->end(); ++it) | |
19293 { | |
19294 if (m_compare(it->first, key)) | |
19295 { | |
19296 return it; | |
19297 } | |
19298 } | |
19299 return Container::end(); | |
19300 } | |
19301 | |
19302 template<class KeyType, detail::enable_if_t< | |
19303 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> | |
19304 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) | |
19305 { | |
19306 for (auto it = this->begin(); it != this->end(); ++it) | |
19307 { | |
19308 if (m_compare(it->first, key)) | |
19309 { | |
19310 return it; | |
19311 } | |
19312 } | |
19313 return Container::end(); | |
19314 } | |
19315 | |
19316 const_iterator find(const key_type& key) const | |
19317 { | |
19318 for (auto it = this->begin(); it != this->end(); ++it) | |
19319 { | |
19320 if (m_compare(it->first, key)) | |
19321 { | |
19322 return it; | |
19323 } | |
19324 } | |
19325 return Container::end(); | |
19326 } | |
19327 | |
19328 std::pair<iterator, bool> insert( value_type&& value ) | |
19329 { | |
19330 return emplace(value.first, std::move(value.second)); | |
19331 } | |
19332 | |
19333 std::pair<iterator, bool> insert( const value_type& value ) | |
19334 { | |
19335 for (auto it = this->begin(); it != this->end(); ++it) | |
19336 { | |
19337 if (m_compare(it->first, value.first)) | |
19338 { | |
19339 return {it, false}; | |
19340 } | |
19341 } | |
19342 Container::push_back(value); | |
19343 return {--this->end(), true}; | |
19344 } | |
19345 | |
19346 template<typename InputIt> | |
19347 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, | |
19348 std::input_iterator_tag>::value>::type; | |
19349 | |
19350 template<typename InputIt, typename = require_input_iter<InputIt>> | |
19351 void insert(InputIt first, InputIt last) | |
19352 { | |
19353 for (auto it = first; it != last; ++it) | |
19354 { | |
19355 insert(*it); | |
19356 } | |
19357 } | |
19358 | |
19359 private: | |
19360 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); | |
19361 }; | |
19362 | |
19363 NLOHMANN_JSON_NAMESPACE_END | |
19364 | |
19365 | |
19366 #if defined(JSON_HAS_CPP_17) | |
19367 #if JSON_HAS_STATIC_RTTI | |
19368 #include <any> | |
19369 #endif | |
19370 #include <string_view> | |
19371 #endif | |
19372 | |
19373 /*! | |
19374 @brief namespace for Niels Lohmann | |
19375 @see https://github.com/nlohmann | |
19376 @since version 1.0.0 | |
19377 */ | |
19378 NLOHMANN_JSON_NAMESPACE_BEGIN | |
19379 | |
19380 /*! | |
19381 @brief a class to store JSON values | |
19382 | |
19383 @internal | |
19384 @invariant The member variables @a m_value and @a m_type have the following | |
19385 relationship: | |
19386 - If `m_type == value_t::object`, then `m_value.object != nullptr`. | |
19387 - If `m_type == value_t::array`, then `m_value.array != nullptr`. | |
19388 - If `m_type == value_t::string`, then `m_value.string != nullptr`. | |
19389 The invariants are checked by member function assert_invariant(). | |
19390 | |
19391 @note ObjectType trick from https://stackoverflow.com/a/9860911 | |
19392 @endinternal | |
19393 | |
19394 @since version 1.0.0 | |
19395 | |
19396 @nosubgrouping | |
19397 */ | |
19398 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
19399 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) | |
19400 : public ::nlohmann::detail::json_base_class<CustomBaseClass> | |
19401 { | |
19402 private: | |
19403 template<detail::value_t> friend struct detail::external_constructor; | |
19404 | |
19405 template<typename> | |
19406 friend class ::nlohmann::json_pointer; | |
19407 // can be restored when json_pointer backwards compatibility is removed | |
19408 // friend ::nlohmann::json_pointer<StringType>; | |
19409 | |
19410 template<typename BasicJsonType, typename InputType> | |
19411 friend class ::nlohmann::detail::parser; | |
19412 friend ::nlohmann::detail::serializer<basic_json>; | |
19413 template<typename BasicJsonType> | |
19414 friend class ::nlohmann::detail::iter_impl; | |
19415 template<typename BasicJsonType, typename CharType> | |
19416 friend class ::nlohmann::detail::binary_writer; | |
19417 template<typename BasicJsonType, typename InputType, typename SAX> | |
19418 friend class ::nlohmann::detail::binary_reader; | |
19419 template<typename BasicJsonType> | |
19420 friend class ::nlohmann::detail::json_sax_dom_parser; | |
19421 template<typename BasicJsonType> | |
19422 friend class ::nlohmann::detail::json_sax_dom_callback_parser; | |
19423 friend class ::nlohmann::detail::exception; | |
19424 | |
19425 /// workaround type for MSVC | |
19426 using basic_json_t = NLOHMANN_BASIC_JSON_TPL; | |
19427 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; | |
19428 | |
19429 JSON_PRIVATE_UNLESS_TESTED: | |
19430 // convenience aliases for types residing in namespace detail; | |
19431 using lexer = ::nlohmann::detail::lexer_base<basic_json>; | |
19432 | |
19433 template<typename InputAdapterType> | |
19434 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser( | |
19435 InputAdapterType adapter, | |
19436 detail::parser_callback_t<basic_json>cb = nullptr, | |
19437 const bool allow_exceptions = true, | |
19438 const bool ignore_comments = false | |
19439 ) | |
19440 { | |
19441 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), | |
19442 std::move(cb), allow_exceptions, ignore_comments); | |
19443 } | |
19444 | |
19445 private: | |
19446 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; | |
19447 template<typename BasicJsonType> | |
19448 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; | |
19449 template<typename BasicJsonType> | |
19450 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; | |
19451 template<typename Iterator> | |
19452 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; | |
19453 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; | |
19454 | |
19455 template<typename CharType> | |
19456 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; | |
19457 | |
19458 template<typename InputType> | |
19459 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>; | |
19460 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; | |
19461 | |
19462 JSON_PRIVATE_UNLESS_TESTED: | |
19463 using serializer = ::nlohmann::detail::serializer<basic_json>; | |
19464 | |
19465 public: | |
19466 using value_t = detail::value_t; | |
19467 /// JSON Pointer, see @ref nlohmann::json_pointer | |
19468 using json_pointer = ::nlohmann::json_pointer<StringType>; | |
19469 template<typename T, typename SFINAE> | |
19470 using json_serializer = JSONSerializer<T, SFINAE>; | |
19471 /// how to treat decoding errors | |
19472 using error_handler_t = detail::error_handler_t; | |
19473 /// how to treat CBOR tags | |
19474 using cbor_tag_handler_t = detail::cbor_tag_handler_t; | |
19475 /// helper type for initializer lists of basic_json values | |
19476 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; | |
19477 | |
19478 using input_format_t = detail::input_format_t; | |
19479 /// SAX interface type, see @ref nlohmann::json_sax | |
19480 using json_sax_t = json_sax<basic_json>; | |
19481 | |
19482 //////////////// | |
19483 // exceptions // | |
19484 //////////////// | |
19485 | |
19486 /// @name exceptions | |
19487 /// Classes to implement user-defined exceptions. | |
19488 /// @{ | |
19489 | |
19490 using exception = detail::exception; | |
19491 using parse_error = detail::parse_error; | |
19492 using invalid_iterator = detail::invalid_iterator; | |
19493 using type_error = detail::type_error; | |
19494 using out_of_range = detail::out_of_range; | |
19495 using other_error = detail::other_error; | |
19496 | |
19497 /// @} | |
19498 | |
19499 ///////////////////// | |
19500 // container types // | |
19501 ///////////////////// | |
19502 | |
19503 /// @name container types | |
19504 /// The canonic container types to use @ref basic_json like any other STL | |
19505 /// container. | |
19506 /// @{ | |
19507 | |
19508 /// the type of elements in a basic_json container | |
19509 using value_type = basic_json; | |
19510 | |
19511 /// the type of an element reference | |
19512 using reference = value_type&; | |
19513 /// the type of an element const reference | |
19514 using const_reference = const value_type&; | |
19515 | |
19516 /// a type to represent differences between iterators | |
19517 using difference_type = std::ptrdiff_t; | |
19518 /// a type to represent container sizes | |
19519 using size_type = std::size_t; | |
19520 | |
19521 /// the allocator type | |
19522 using allocator_type = AllocatorType<basic_json>; | |
19523 | |
19524 /// the type of an element pointer | |
19525 using pointer = typename std::allocator_traits<allocator_type>::pointer; | |
19526 /// the type of an element const pointer | |
19527 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; | |
19528 | |
19529 /// an iterator for a basic_json container | |
19530 using iterator = iter_impl<basic_json>; | |
19531 /// a const iterator for a basic_json container | |
19532 using const_iterator = iter_impl<const basic_json>; | |
19533 /// a reverse iterator for a basic_json container | |
19534 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; | |
19535 /// a const reverse iterator for a basic_json container | |
19536 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; | |
19537 | |
19538 /// @} | |
19539 | |
19540 /// @brief returns the allocator associated with the container | |
19541 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ | |
19542 static allocator_type get_allocator() | |
19543 { | |
19544 return allocator_type(); | |
19545 } | |
19546 | |
19547 /// @brief returns version information on the library | |
19548 /// @sa https://json.nlohmann.me/api/basic_json/meta/ | |
19549 JSON_HEDLEY_WARN_UNUSED_RESULT | |
19550 static basic_json meta() | |
19551 { | |
19552 basic_json result; | |
19553 | |
19554 result["copyright"] = "(C) 2013-2023 Niels Lohmann"; | |
19555 result["name"] = "JSON for Modern C++"; | |
19556 result["url"] = "https://github.com/nlohmann/json"; | |
19557 result["version"]["string"] = | |
19558 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.', | |
19559 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.', | |
19560 std::to_string(NLOHMANN_JSON_VERSION_PATCH)); | |
19561 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; | |
19562 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; | |
19563 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; | |
19564 | |
19565 #ifdef _WIN32 | |
19566 result["platform"] = "win32"; | |
19567 #elif defined __linux__ | |
19568 result["platform"] = "linux"; | |
19569 #elif defined __APPLE__ | |
19570 result["platform"] = "apple"; | |
19571 #elif defined __unix__ | |
19572 result["platform"] = "unix"; | |
19573 #else | |
19574 result["platform"] = "unknown"; | |
19575 #endif | |
19576 | |
19577 #if defined(__ICC) || defined(__INTEL_COMPILER) | |
19578 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; | |
19579 #elif defined(__clang__) | |
19580 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; | |
19581 #elif defined(__GNUC__) || defined(__GNUG__) | |
19582 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat( | |
19583 std::to_string(__GNUC__), '.', | |
19584 std::to_string(__GNUC_MINOR__), '.', | |
19585 std::to_string(__GNUC_PATCHLEVEL__)) | |
19586 } | |
19587 }; | |
19588 #elif defined(__HP_cc) || defined(__HP_aCC) | |
19589 result["compiler"] = "hp" | |
19590 #elif defined(__IBMCPP__) | |
19591 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; | |
19592 #elif defined(_MSC_VER) | |
19593 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; | |
19594 #elif defined(__PGI) | |
19595 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; | |
19596 #elif defined(__SUNPRO_CC) | |
19597 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; | |
19598 #else | |
19599 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; | |
19600 #endif | |
19601 | |
19602 #if defined(_MSVC_LANG) | |
19603 result["compiler"]["c++"] = std::to_string(_MSVC_LANG); | |
19604 #elif defined(__cplusplus) | |
19605 result["compiler"]["c++"] = std::to_string(__cplusplus); | |
19606 #else | |
19607 result["compiler"]["c++"] = "unknown"; | |
19608 #endif | |
19609 return result; | |
19610 } | |
19611 | |
19612 /////////////////////////// | |
19613 // JSON value data types // | |
19614 /////////////////////////// | |
19615 | |
19616 /// @name JSON value data types | |
19617 /// The data types to store a JSON value. These types are derived from | |
19618 /// the template arguments passed to class @ref basic_json. | |
19619 /// @{ | |
19620 | |
19621 /// @brief default object key comparator type | |
19622 /// The actual object key comparator type (@ref object_comparator_t) may be | |
19623 /// different. | |
19624 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ | |
19625 #if defined(JSON_HAS_CPP_14) | |
19626 // use of transparent comparator avoids unnecessary repeated construction of temporaries | |
19627 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType) | |
19628 using default_object_comparator_t = std::less<>; | |
19629 #else | |
19630 using default_object_comparator_t = std::less<StringType>; | |
19631 #endif | |
19632 | |
19633 /// @brief a type for an object | |
19634 /// @sa https://json.nlohmann.me/api/basic_json/object_t/ | |
19635 using object_t = ObjectType<StringType, | |
19636 basic_json, | |
19637 default_object_comparator_t, | |
19638 AllocatorType<std::pair<const StringType, | |
19639 basic_json>>>; | |
19640 | |
19641 /// @brief a type for an array | |
19642 /// @sa https://json.nlohmann.me/api/basic_json/array_t/ | |
19643 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; | |
19644 | |
19645 /// @brief a type for a string | |
19646 /// @sa https://json.nlohmann.me/api/basic_json/string_t/ | |
19647 using string_t = StringType; | |
19648 | |
19649 /// @brief a type for a boolean | |
19650 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ | |
19651 using boolean_t = BooleanType; | |
19652 | |
19653 /// @brief a type for a number (integer) | |
19654 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ | |
19655 using number_integer_t = NumberIntegerType; | |
19656 | |
19657 /// @brief a type for a number (unsigned) | |
19658 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ | |
19659 using number_unsigned_t = NumberUnsignedType; | |
19660 | |
19661 /// @brief a type for a number (floating-point) | |
19662 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ | |
19663 using number_float_t = NumberFloatType; | |
19664 | |
19665 /// @brief a type for a packed binary type | |
19666 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ | |
19667 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>; | |
19668 | |
19669 /// @brief object key comparator type | |
19670 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ | |
19671 using object_comparator_t = detail::actual_object_comparator_t<basic_json>; | |
19672 | |
19673 /// @} | |
19674 | |
19675 private: | |
19676 | |
19677 /// helper for exception-safe object creation | |
19678 template<typename T, typename... Args> | |
19679 JSON_HEDLEY_RETURNS_NON_NULL | |
19680 static T* create(Args&& ... args) | |
19681 { | |
19682 AllocatorType<T> alloc; | |
19683 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; | |
19684 | |
19685 auto deleter = [&](T * obj) | |
19686 { | |
19687 AllocatorTraits::deallocate(alloc, obj, 1); | |
19688 }; | |
19689 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter); | |
19690 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...); | |
19691 JSON_ASSERT(obj != nullptr); | |
19692 return obj.release(); | |
19693 } | |
19694 | |
19695 //////////////////////// | |
19696 // JSON value storage // | |
19697 //////////////////////// | |
19698 | |
19699 JSON_PRIVATE_UNLESS_TESTED: | |
19700 /*! | |
19701 @brief a JSON value | |
19702 | |
19703 The actual storage for a JSON value of the @ref basic_json class. This | |
19704 union combines the different storage types for the JSON value types | |
19705 defined in @ref value_t. | |
19706 | |
19707 JSON type | value_t type | used type | |
19708 --------- | --------------- | ------------------------ | |
19709 object | object | pointer to @ref object_t | |
19710 array | array | pointer to @ref array_t | |
19711 string | string | pointer to @ref string_t | |
19712 boolean | boolean | @ref boolean_t | |
19713 number | number_integer | @ref number_integer_t | |
19714 number | number_unsigned | @ref number_unsigned_t | |
19715 number | number_float | @ref number_float_t | |
19716 binary | binary | pointer to @ref binary_t | |
19717 null | null | *no value is stored* | |
19718 | |
19719 @note Variable-length types (objects, arrays, and strings) are stored as | |
19720 pointers. The size of the union should not exceed 64 bits if the default | |
19721 value types are used. | |
19722 | |
19723 @since version 1.0.0 | |
19724 */ | |
19725 union json_value | |
19726 { | |
19727 /// object (stored with pointer to save storage) | |
19728 object_t* object; | |
19729 /// array (stored with pointer to save storage) | |
19730 array_t* array; | |
19731 /// string (stored with pointer to save storage) | |
19732 string_t* string; | |
19733 /// binary (stored with pointer to save storage) | |
19734 binary_t* binary; | |
19735 /// boolean | |
19736 boolean_t boolean; | |
19737 /// number (integer) | |
19738 number_integer_t number_integer; | |
19739 /// number (unsigned integer) | |
19740 number_unsigned_t number_unsigned; | |
19741 /// number (floating-point) | |
19742 number_float_t number_float; | |
19743 | |
19744 /// default constructor (for null values) | |
19745 json_value() = default; | |
19746 /// constructor for booleans | |
19747 json_value(boolean_t v) noexcept : boolean(v) {} | |
19748 /// constructor for numbers (integer) | |
19749 json_value(number_integer_t v) noexcept : number_integer(v) {} | |
19750 /// constructor for numbers (unsigned) | |
19751 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} | |
19752 /// constructor for numbers (floating-point) | |
19753 json_value(number_float_t v) noexcept : number_float(v) {} | |
19754 /// constructor for empty values of a given type | |
19755 json_value(value_t t) | |
19756 { | |
19757 switch (t) | |
19758 { | |
19759 case value_t::object: | |
19760 { | |
19761 object = create<object_t>(); | |
19762 break; | |
19763 } | |
19764 | |
19765 case value_t::array: | |
19766 { | |
19767 array = create<array_t>(); | |
19768 break; | |
19769 } | |
19770 | |
19771 case value_t::string: | |
19772 { | |
19773 string = create<string_t>(""); | |
19774 break; | |
19775 } | |
19776 | |
19777 case value_t::binary: | |
19778 { | |
19779 binary = create<binary_t>(); | |
19780 break; | |
19781 } | |
19782 | |
19783 case value_t::boolean: | |
19784 { | |
19785 boolean = static_cast<boolean_t>(false); | |
19786 break; | |
19787 } | |
19788 | |
19789 case value_t::number_integer: | |
19790 { | |
19791 number_integer = static_cast<number_integer_t>(0); | |
19792 break; | |
19793 } | |
19794 | |
19795 case value_t::number_unsigned: | |
19796 { | |
19797 number_unsigned = static_cast<number_unsigned_t>(0); | |
19798 break; | |
19799 } | |
19800 | |
19801 case value_t::number_float: | |
19802 { | |
19803 number_float = static_cast<number_float_t>(0.0); | |
19804 break; | |
19805 } | |
19806 | |
19807 case value_t::null: | |
19808 { | |
19809 object = nullptr; // silence warning, see #821 | |
19810 break; | |
19811 } | |
19812 | |
19813 case value_t::discarded: | |
19814 default: | |
19815 { | |
19816 object = nullptr; // silence warning, see #821 | |
19817 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) | |
19818 { | |
19819 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE | |
19820 } | |
19821 break; | |
19822 } | |
19823 } | |
19824 } | |
19825 | |
19826 /// constructor for strings | |
19827 json_value(const string_t& value) : string(create<string_t>(value)) {} | |
19828 | |
19829 /// constructor for rvalue strings | |
19830 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {} | |
19831 | |
19832 /// constructor for objects | |
19833 json_value(const object_t& value) : object(create<object_t>(value)) {} | |
19834 | |
19835 /// constructor for rvalue objects | |
19836 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {} | |
19837 | |
19838 /// constructor for arrays | |
19839 json_value(const array_t& value) : array(create<array_t>(value)) {} | |
19840 | |
19841 /// constructor for rvalue arrays | |
19842 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {} | |
19843 | |
19844 /// constructor for binary arrays | |
19845 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {} | |
19846 | |
19847 /// constructor for rvalue binary arrays | |
19848 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {} | |
19849 | |
19850 /// constructor for binary arrays (internal type) | |
19851 json_value(const binary_t& value) : binary(create<binary_t>(value)) {} | |
19852 | |
19853 /// constructor for rvalue binary arrays (internal type) | |
19854 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} | |
19855 | |
19856 void destroy(value_t t) | |
19857 { | |
19858 if ( | |
19859 (t == value_t::object && object == nullptr) || | |
19860 (t == value_t::array && array == nullptr) || | |
19861 (t == value_t::string && string == nullptr) || | |
19862 (t == value_t::binary && binary == nullptr) | |
19863 ) | |
19864 { | |
19865 //not initialized (e.g. due to exception in the ctor) | |
19866 return; | |
19867 } | |
19868 if (t == value_t::array || t == value_t::object) | |
19869 { | |
19870 // flatten the current json_value to a heap-allocated stack | |
19871 std::vector<basic_json> stack; | |
19872 | |
19873 // move the top-level items to stack | |
19874 if (t == value_t::array) | |
19875 { | |
19876 stack.reserve(array->size()); | |
19877 std::move(array->begin(), array->end(), std::back_inserter(stack)); | |
19878 } | |
19879 else | |
19880 { | |
19881 stack.reserve(object->size()); | |
19882 for (auto&& it : *object) | |
19883 { | |
19884 stack.push_back(std::move(it.second)); | |
19885 } | |
19886 } | |
19887 | |
19888 while (!stack.empty()) | |
19889 { | |
19890 // move the last item to local variable to be processed | |
19891 basic_json current_item(std::move(stack.back())); | |
19892 stack.pop_back(); | |
19893 | |
19894 // if current_item is array/object, move | |
19895 // its children to the stack to be processed later | |
19896 if (current_item.is_array()) | |
19897 { | |
19898 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); | |
19899 | |
19900 current_item.m_data.m_value.array->clear(); | |
19901 } | |
19902 else if (current_item.is_object()) | |
19903 { | |
19904 for (auto&& it : *current_item.m_data.m_value.object) | |
19905 { | |
19906 stack.push_back(std::move(it.second)); | |
19907 } | |
19908 | |
19909 current_item.m_data.m_value.object->clear(); | |
19910 } | |
19911 | |
19912 // it's now safe that current_item get destructed | |
19913 // since it doesn't have any children | |
19914 } | |
19915 } | |
19916 | |
19917 switch (t) | |
19918 { | |
19919 case value_t::object: | |
19920 { | |
19921 AllocatorType<object_t> alloc; | |
19922 std::allocator_traits<decltype(alloc)>::destroy(alloc, object); | |
19923 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); | |
19924 break; | |
19925 } | |
19926 | |
19927 case value_t::array: | |
19928 { | |
19929 AllocatorType<array_t> alloc; | |
19930 std::allocator_traits<decltype(alloc)>::destroy(alloc, array); | |
19931 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); | |
19932 break; | |
19933 } | |
19934 | |
19935 case value_t::string: | |
19936 { | |
19937 AllocatorType<string_t> alloc; | |
19938 std::allocator_traits<decltype(alloc)>::destroy(alloc, string); | |
19939 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); | |
19940 break; | |
19941 } | |
19942 | |
19943 case value_t::binary: | |
19944 { | |
19945 AllocatorType<binary_t> alloc; | |
19946 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary); | |
19947 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1); | |
19948 break; | |
19949 } | |
19950 | |
19951 case value_t::null: | |
19952 case value_t::boolean: | |
19953 case value_t::number_integer: | |
19954 case value_t::number_unsigned: | |
19955 case value_t::number_float: | |
19956 case value_t::discarded: | |
19957 default: | |
19958 { | |
19959 break; | |
19960 } | |
19961 } | |
19962 } | |
19963 }; | |
19964 | |
19965 private: | |
19966 /*! | |
19967 @brief checks the class invariants | |
19968 | |
19969 This function asserts the class invariants. It needs to be called at the | |
19970 end of every constructor to make sure that created objects respect the | |
19971 invariant. Furthermore, it has to be called each time the type of a JSON | |
19972 value is changed, because the invariant expresses a relationship between | |
19973 @a m_type and @a m_value. | |
19974 | |
19975 Furthermore, the parent relation is checked for arrays and objects: If | |
19976 @a check_parents true and the value is an array or object, then the | |
19977 container's elements must have the current value as parent. | |
19978 | |
19979 @param[in] check_parents whether the parent relation should be checked. | |
19980 The value is true by default and should only be set to false | |
19981 during destruction of objects when the invariant does not | |
19982 need to hold. | |
19983 */ | |
19984 void assert_invariant(bool check_parents = true) const noexcept | |
19985 { | |
19986 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); | |
19987 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); | |
19988 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); | |
19989 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); | |
19990 | |
19991 #if JSON_DIAGNOSTICS | |
19992 JSON_TRY | |
19993 { | |
19994 // cppcheck-suppress assertWithSideEffect | |
19995 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) | |
19996 { | |
19997 return j.m_parent == this; | |
19998 })); | |
19999 } | |
20000 JSON_CATCH(...) {} // LCOV_EXCL_LINE | |
20001 #endif | |
20002 static_cast<void>(check_parents); | |
20003 } | |
20004 | |
20005 void set_parents() | |
20006 { | |
20007 #if JSON_DIAGNOSTICS | |
20008 switch (m_data.m_type) | |
20009 { | |
20010 case value_t::array: | |
20011 { | |
20012 for (auto& element : *m_data.m_value.array) | |
20013 { | |
20014 element.m_parent = this; | |
20015 } | |
20016 break; | |
20017 } | |
20018 | |
20019 case value_t::object: | |
20020 { | |
20021 for (auto& element : *m_data.m_value.object) | |
20022 { | |
20023 element.second.m_parent = this; | |
20024 } | |
20025 break; | |
20026 } | |
20027 | |
20028 case value_t::null: | |
20029 case value_t::string: | |
20030 case value_t::boolean: | |
20031 case value_t::number_integer: | |
20032 case value_t::number_unsigned: | |
20033 case value_t::number_float: | |
20034 case value_t::binary: | |
20035 case value_t::discarded: | |
20036 default: | |
20037 break; | |
20038 } | |
20039 #endif | |
20040 } | |
20041 | |
20042 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) | |
20043 { | |
20044 #if JSON_DIAGNOSTICS | |
20045 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) | |
20046 { | |
20047 (it + i)->m_parent = this; | |
20048 } | |
20049 #else | |
20050 static_cast<void>(count_set_parents); | |
20051 #endif | |
20052 return it; | |
20053 } | |
20054 | |
20055 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) | |
20056 { | |
20057 #if JSON_DIAGNOSTICS | |
20058 if (old_capacity != static_cast<std::size_t>(-1)) | |
20059 { | |
20060 // see https://github.com/nlohmann/json/issues/2838 | |
20061 JSON_ASSERT(type() == value_t::array); | |
20062 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) | |
20063 { | |
20064 // capacity has changed: update all parents | |
20065 set_parents(); | |
20066 return j; | |
20067 } | |
20068 } | |
20069 | |
20070 // ordered_json uses a vector internally, so pointers could have | |
20071 // been invalidated; see https://github.com/nlohmann/json/issues/2962 | |
20072 #ifdef JSON_HEDLEY_MSVC_VERSION | |
20073 #pragma warning(push ) | |
20074 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr | |
20075 #endif | |
20076 if (detail::is_ordered_map<object_t>::value) | |
20077 { | |
20078 set_parents(); | |
20079 return j; | |
20080 } | |
20081 #ifdef JSON_HEDLEY_MSVC_VERSION | |
20082 #pragma warning( pop ) | |
20083 #endif | |
20084 | |
20085 j.m_parent = this; | |
20086 #else | |
20087 static_cast<void>(j); | |
20088 static_cast<void>(old_capacity); | |
20089 #endif | |
20090 return j; | |
20091 } | |
20092 | |
20093 public: | |
20094 ////////////////////////// | |
20095 // JSON parser callback // | |
20096 ////////////////////////// | |
20097 | |
20098 /// @brief parser event types | |
20099 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ | |
20100 using parse_event_t = detail::parse_event_t; | |
20101 | |
20102 /// @brief per-element parser callback type | |
20103 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ | |
20104 using parser_callback_t = detail::parser_callback_t<basic_json>; | |
20105 | |
20106 ////////////////// | |
20107 // constructors // | |
20108 ////////////////// | |
20109 | |
20110 /// @name constructors and destructors | |
20111 /// Constructors of class @ref basic_json, copy/move constructor, copy | |
20112 /// assignment, static functions creating objects, and the destructor. | |
20113 /// @{ | |
20114 | |
20115 /// @brief create an empty value with a given type | |
20116 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20117 basic_json(const value_t v) | |
20118 : m_data(v) | |
20119 { | |
20120 assert_invariant(); | |
20121 } | |
20122 | |
20123 /// @brief create a null object | |
20124 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20125 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape) | |
20126 : basic_json(value_t::null) | |
20127 { | |
20128 assert_invariant(); | |
20129 } | |
20130 | |
20131 /// @brief create a JSON value from compatible types | |
20132 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20133 template < typename CompatibleType, | |
20134 typename U = detail::uncvref_t<CompatibleType>, | |
20135 detail::enable_if_t < | |
20136 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 > | |
20137 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) | |
20138 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), | |
20139 std::forward<CompatibleType>(val)))) | |
20140 { | |
20141 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); | |
20142 set_parents(); | |
20143 assert_invariant(); | |
20144 } | |
20145 | |
20146 /// @brief create a JSON value from an existing one | |
20147 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20148 template < typename BasicJsonType, | |
20149 detail::enable_if_t < | |
20150 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > | |
20151 basic_json(const BasicJsonType& val) | |
20152 { | |
20153 using other_boolean_t = typename BasicJsonType::boolean_t; | |
20154 using other_number_float_t = typename BasicJsonType::number_float_t; | |
20155 using other_number_integer_t = typename BasicJsonType::number_integer_t; | |
20156 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; | |
20157 using other_string_t = typename BasicJsonType::string_t; | |
20158 using other_object_t = typename BasicJsonType::object_t; | |
20159 using other_array_t = typename BasicJsonType::array_t; | |
20160 using other_binary_t = typename BasicJsonType::binary_t; | |
20161 | |
20162 switch (val.type()) | |
20163 { | |
20164 case value_t::boolean: | |
20165 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); | |
20166 break; | |
20167 case value_t::number_float: | |
20168 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); | |
20169 break; | |
20170 case value_t::number_integer: | |
20171 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); | |
20172 break; | |
20173 case value_t::number_unsigned: | |
20174 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); | |
20175 break; | |
20176 case value_t::string: | |
20177 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); | |
20178 break; | |
20179 case value_t::object: | |
20180 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); | |
20181 break; | |
20182 case value_t::array: | |
20183 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); | |
20184 break; | |
20185 case value_t::binary: | |
20186 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>()); | |
20187 break; | |
20188 case value_t::null: | |
20189 *this = nullptr; | |
20190 break; | |
20191 case value_t::discarded: | |
20192 m_data.m_type = value_t::discarded; | |
20193 break; | |
20194 default: // LCOV_EXCL_LINE | |
20195 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
20196 } | |
20197 JSON_ASSERT(m_data.m_type == val.type()); | |
20198 set_parents(); | |
20199 assert_invariant(); | |
20200 } | |
20201 | |
20202 /// @brief create a container (array or object) from an initializer list | |
20203 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20204 basic_json(initializer_list_t init, | |
20205 bool type_deduction = true, | |
20206 value_t manual_type = value_t::array) | |
20207 { | |
20208 // check if each element is an array with two elements whose first | |
20209 // element is a string | |
20210 bool is_an_object = std::all_of(init.begin(), init.end(), | |
20211 [](const detail::json_ref<basic_json>& element_ref) | |
20212 { | |
20213 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; | |
20214 // (many string types can be constructed from 0 via its null-pointer guise, so we get a | |
20215 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) | |
20216 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string(); | |
20217 }); | |
20218 | |
20219 // adjust type if type deduction is not wanted | |
20220 if (!type_deduction) | |
20221 { | |
20222 // if array is wanted, do not create an object though possible | |
20223 if (manual_type == value_t::array) | |
20224 { | |
20225 is_an_object = false; | |
20226 } | |
20227 | |
20228 // if object is wanted but impossible, throw an exception | |
20229 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) | |
20230 { | |
20231 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr)); | |
20232 } | |
20233 } | |
20234 | |
20235 if (is_an_object) | |
20236 { | |
20237 // the initializer list is a list of pairs -> create object | |
20238 m_data.m_type = value_t::object; | |
20239 m_data.m_value = value_t::object; | |
20240 | |
20241 for (auto& element_ref : init) | |
20242 { | |
20243 auto element = element_ref.moved_or_copied(); | |
20244 m_data.m_value.object->emplace( | |
20245 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), | |
20246 std::move((*element.m_data.m_value.array)[1])); | |
20247 } | |
20248 } | |
20249 else | |
20250 { | |
20251 // the initializer list describes an array -> create array | |
20252 m_data.m_type = value_t::array; | |
20253 m_data.m_value.array = create<array_t>(init.begin(), init.end()); | |
20254 } | |
20255 | |
20256 set_parents(); | |
20257 assert_invariant(); | |
20258 } | |
20259 | |
20260 /// @brief explicitly create a binary array (without subtype) | |
20261 /// @sa https://json.nlohmann.me/api/basic_json/binary/ | |
20262 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20263 static basic_json binary(const typename binary_t::container_type& init) | |
20264 { | |
20265 auto res = basic_json(); | |
20266 res.m_data.m_type = value_t::binary; | |
20267 res.m_data.m_value = init; | |
20268 return res; | |
20269 } | |
20270 | |
20271 /// @brief explicitly create a binary array (with subtype) | |
20272 /// @sa https://json.nlohmann.me/api/basic_json/binary/ | |
20273 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20274 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) | |
20275 { | |
20276 auto res = basic_json(); | |
20277 res.m_data.m_type = value_t::binary; | |
20278 res.m_data.m_value = binary_t(init, subtype); | |
20279 return res; | |
20280 } | |
20281 | |
20282 /// @brief explicitly create a binary array | |
20283 /// @sa https://json.nlohmann.me/api/basic_json/binary/ | |
20284 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20285 static basic_json binary(typename binary_t::container_type&& init) | |
20286 { | |
20287 auto res = basic_json(); | |
20288 res.m_data.m_type = value_t::binary; | |
20289 res.m_data.m_value = std::move(init); | |
20290 return res; | |
20291 } | |
20292 | |
20293 /// @brief explicitly create a binary array (with subtype) | |
20294 /// @sa https://json.nlohmann.me/api/basic_json/binary/ | |
20295 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20296 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) | |
20297 { | |
20298 auto res = basic_json(); | |
20299 res.m_data.m_type = value_t::binary; | |
20300 res.m_data.m_value = binary_t(std::move(init), subtype); | |
20301 return res; | |
20302 } | |
20303 | |
20304 /// @brief explicitly create an array from an initializer list | |
20305 /// @sa https://json.nlohmann.me/api/basic_json/array/ | |
20306 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20307 static basic_json array(initializer_list_t init = {}) | |
20308 { | |
20309 return basic_json(init, false, value_t::array); | |
20310 } | |
20311 | |
20312 /// @brief explicitly create an object from an initializer list | |
20313 /// @sa https://json.nlohmann.me/api/basic_json/object/ | |
20314 JSON_HEDLEY_WARN_UNUSED_RESULT | |
20315 static basic_json object(initializer_list_t init = {}) | |
20316 { | |
20317 return basic_json(init, false, value_t::object); | |
20318 } | |
20319 | |
20320 /// @brief construct an array with count copies of given value | |
20321 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20322 basic_json(size_type cnt, const basic_json& val): | |
20323 m_data{cnt, val} | |
20324 { | |
20325 set_parents(); | |
20326 assert_invariant(); | |
20327 } | |
20328 | |
20329 /// @brief construct a JSON container given an iterator range | |
20330 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20331 template < class InputIT, typename std::enable_if < | |
20332 std::is_same<InputIT, typename basic_json_t::iterator>::value || | |
20333 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > | |
20334 basic_json(InputIT first, InputIT last) | |
20335 { | |
20336 JSON_ASSERT(first.m_object != nullptr); | |
20337 JSON_ASSERT(last.m_object != nullptr); | |
20338 | |
20339 // make sure iterator fits the current value | |
20340 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) | |
20341 { | |
20342 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr)); | |
20343 } | |
20344 | |
20345 // copy type from first iterator | |
20346 m_data.m_type = first.m_object->m_data.m_type; | |
20347 | |
20348 // check if iterator range is complete for primitive values | |
20349 switch (m_data.m_type) | |
20350 { | |
20351 case value_t::boolean: | |
20352 case value_t::number_float: | |
20353 case value_t::number_integer: | |
20354 case value_t::number_unsigned: | |
20355 case value_t::string: | |
20356 { | |
20357 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() | |
20358 || !last.m_it.primitive_iterator.is_end())) | |
20359 { | |
20360 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object)); | |
20361 } | |
20362 break; | |
20363 } | |
20364 | |
20365 case value_t::null: | |
20366 case value_t::object: | |
20367 case value_t::array: | |
20368 case value_t::binary: | |
20369 case value_t::discarded: | |
20370 default: | |
20371 break; | |
20372 } | |
20373 | |
20374 switch (m_data.m_type) | |
20375 { | |
20376 case value_t::number_integer: | |
20377 { | |
20378 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; | |
20379 break; | |
20380 } | |
20381 | |
20382 case value_t::number_unsigned: | |
20383 { | |
20384 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; | |
20385 break; | |
20386 } | |
20387 | |
20388 case value_t::number_float: | |
20389 { | |
20390 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; | |
20391 break; | |
20392 } | |
20393 | |
20394 case value_t::boolean: | |
20395 { | |
20396 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; | |
20397 break; | |
20398 } | |
20399 | |
20400 case value_t::string: | |
20401 { | |
20402 m_data.m_value = *first.m_object->m_data.m_value.string; | |
20403 break; | |
20404 } | |
20405 | |
20406 case value_t::object: | |
20407 { | |
20408 m_data.m_value.object = create<object_t>(first.m_it.object_iterator, | |
20409 last.m_it.object_iterator); | |
20410 break; | |
20411 } | |
20412 | |
20413 case value_t::array: | |
20414 { | |
20415 m_data.m_value.array = create<array_t>(first.m_it.array_iterator, | |
20416 last.m_it.array_iterator); | |
20417 break; | |
20418 } | |
20419 | |
20420 case value_t::binary: | |
20421 { | |
20422 m_data.m_value = *first.m_object->m_data.m_value.binary; | |
20423 break; | |
20424 } | |
20425 | |
20426 case value_t::null: | |
20427 case value_t::discarded: | |
20428 default: | |
20429 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object)); | |
20430 } | |
20431 | |
20432 set_parents(); | |
20433 assert_invariant(); | |
20434 } | |
20435 | |
20436 /////////////////////////////////////// | |
20437 // other constructors and destructor // | |
20438 /////////////////////////////////////// | |
20439 | |
20440 template<typename JsonRef, | |
20441 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>, | |
20442 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 > | |
20443 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} | |
20444 | |
20445 /// @brief copy constructor | |
20446 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20447 basic_json(const basic_json& other) | |
20448 : json_base_class_t(other) | |
20449 { | |
20450 m_data.m_type = other.m_data.m_type; | |
20451 // check of passed value is valid | |
20452 other.assert_invariant(); | |
20453 | |
20454 switch (m_data.m_type) | |
20455 { | |
20456 case value_t::object: | |
20457 { | |
20458 m_data.m_value = *other.m_data.m_value.object; | |
20459 break; | |
20460 } | |
20461 | |
20462 case value_t::array: | |
20463 { | |
20464 m_data.m_value = *other.m_data.m_value.array; | |
20465 break; | |
20466 } | |
20467 | |
20468 case value_t::string: | |
20469 { | |
20470 m_data.m_value = *other.m_data.m_value.string; | |
20471 break; | |
20472 } | |
20473 | |
20474 case value_t::boolean: | |
20475 { | |
20476 m_data.m_value = other.m_data.m_value.boolean; | |
20477 break; | |
20478 } | |
20479 | |
20480 case value_t::number_integer: | |
20481 { | |
20482 m_data.m_value = other.m_data.m_value.number_integer; | |
20483 break; | |
20484 } | |
20485 | |
20486 case value_t::number_unsigned: | |
20487 { | |
20488 m_data.m_value = other.m_data.m_value.number_unsigned; | |
20489 break; | |
20490 } | |
20491 | |
20492 case value_t::number_float: | |
20493 { | |
20494 m_data.m_value = other.m_data.m_value.number_float; | |
20495 break; | |
20496 } | |
20497 | |
20498 case value_t::binary: | |
20499 { | |
20500 m_data.m_value = *other.m_data.m_value.binary; | |
20501 break; | |
20502 } | |
20503 | |
20504 case value_t::null: | |
20505 case value_t::discarded: | |
20506 default: | |
20507 break; | |
20508 } | |
20509 | |
20510 set_parents(); | |
20511 assert_invariant(); | |
20512 } | |
20513 | |
20514 /// @brief move constructor | |
20515 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | |
20516 basic_json(basic_json&& other) noexcept | |
20517 : json_base_class_t(std::forward<json_base_class_t>(other)), | |
20518 m_data(std::move(other.m_data)) | |
20519 { | |
20520 // check that passed value is valid | |
20521 other.assert_invariant(false); | |
20522 | |
20523 // invalidate payload | |
20524 other.m_data.m_type = value_t::null; | |
20525 other.m_data.m_value = {}; | |
20526 | |
20527 set_parents(); | |
20528 assert_invariant(); | |
20529 } | |
20530 | |
20531 /// @brief copy assignment | |
20532 /// @sa https://json.nlohmann.me/api/basic_json/operator=/ | |
20533 basic_json& operator=(basic_json other) noexcept ( | |
20534 std::is_nothrow_move_constructible<value_t>::value&& | |
20535 std::is_nothrow_move_assignable<value_t>::value&& | |
20536 std::is_nothrow_move_constructible<json_value>::value&& | |
20537 std::is_nothrow_move_assignable<json_value>::value&& | |
20538 std::is_nothrow_move_assignable<json_base_class_t>::value | |
20539 ) | |
20540 { | |
20541 // check that passed value is valid | |
20542 other.assert_invariant(); | |
20543 | |
20544 using std::swap; | |
20545 swap(m_data.m_type, other.m_data.m_type); | |
20546 swap(m_data.m_value, other.m_data.m_value); | |
20547 json_base_class_t::operator=(std::move(other)); | |
20548 | |
20549 set_parents(); | |
20550 assert_invariant(); | |
20551 return *this; | |
20552 } | |
20553 | |
20554 /// @brief destructor | |
20555 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ | |
20556 ~basic_json() noexcept | |
20557 { | |
20558 assert_invariant(false); | |
20559 } | |
20560 | |
20561 /// @} | |
20562 | |
20563 public: | |
20564 /////////////////////// | |
20565 // object inspection // | |
20566 /////////////////////// | |
20567 | |
20568 /// @name object inspection | |
20569 /// Functions to inspect the type of a JSON value. | |
20570 /// @{ | |
20571 | |
20572 /// @brief serialization | |
20573 /// @sa https://json.nlohmann.me/api/basic_json/dump/ | |
20574 string_t dump(const int indent = -1, | |
20575 const char indent_char = ' ', | |
20576 const bool ensure_ascii = false, | |
20577 const error_handler_t error_handler = error_handler_t::strict) const | |
20578 { | |
20579 string_t result; | |
20580 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); | |
20581 | |
20582 if (indent >= 0) | |
20583 { | |
20584 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); | |
20585 } | |
20586 else | |
20587 { | |
20588 s.dump(*this, false, ensure_ascii, 0); | |
20589 } | |
20590 | |
20591 return result; | |
20592 } | |
20593 | |
20594 /// @brief return the type of the JSON value (explicit) | |
20595 /// @sa https://json.nlohmann.me/api/basic_json/type/ | |
20596 constexpr value_t type() const noexcept | |
20597 { | |
20598 return m_data.m_type; | |
20599 } | |
20600 | |
20601 /// @brief return whether type is primitive | |
20602 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ | |
20603 constexpr bool is_primitive() const noexcept | |
20604 { | |
20605 return is_null() || is_string() || is_boolean() || is_number() || is_binary(); | |
20606 } | |
20607 | |
20608 /// @brief return whether type is structured | |
20609 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ | |
20610 constexpr bool is_structured() const noexcept | |
20611 { | |
20612 return is_array() || is_object(); | |
20613 } | |
20614 | |
20615 /// @brief return whether value is null | |
20616 /// @sa https://json.nlohmann.me/api/basic_json/is_null/ | |
20617 constexpr bool is_null() const noexcept | |
20618 { | |
20619 return m_data.m_type == value_t::null; | |
20620 } | |
20621 | |
20622 /// @brief return whether value is a boolean | |
20623 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ | |
20624 constexpr bool is_boolean() const noexcept | |
20625 { | |
20626 return m_data.m_type == value_t::boolean; | |
20627 } | |
20628 | |
20629 /// @brief return whether value is a number | |
20630 /// @sa https://json.nlohmann.me/api/basic_json/is_number/ | |
20631 constexpr bool is_number() const noexcept | |
20632 { | |
20633 return is_number_integer() || is_number_float(); | |
20634 } | |
20635 | |
20636 /// @brief return whether value is an integer number | |
20637 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ | |
20638 constexpr bool is_number_integer() const noexcept | |
20639 { | |
20640 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; | |
20641 } | |
20642 | |
20643 /// @brief return whether value is an unsigned integer number | |
20644 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ | |
20645 constexpr bool is_number_unsigned() const noexcept | |
20646 { | |
20647 return m_data.m_type == value_t::number_unsigned; | |
20648 } | |
20649 | |
20650 /// @brief return whether value is a floating-point number | |
20651 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ | |
20652 constexpr bool is_number_float() const noexcept | |
20653 { | |
20654 return m_data.m_type == value_t::number_float; | |
20655 } | |
20656 | |
20657 /// @brief return whether value is an object | |
20658 /// @sa https://json.nlohmann.me/api/basic_json/is_object/ | |
20659 constexpr bool is_object() const noexcept | |
20660 { | |
20661 return m_data.m_type == value_t::object; | |
20662 } | |
20663 | |
20664 /// @brief return whether value is an array | |
20665 /// @sa https://json.nlohmann.me/api/basic_json/is_array/ | |
20666 constexpr bool is_array() const noexcept | |
20667 { | |
20668 return m_data.m_type == value_t::array; | |
20669 } | |
20670 | |
20671 /// @brief return whether value is a string | |
20672 /// @sa https://json.nlohmann.me/api/basic_json/is_string/ | |
20673 constexpr bool is_string() const noexcept | |
20674 { | |
20675 return m_data.m_type == value_t::string; | |
20676 } | |
20677 | |
20678 /// @brief return whether value is a binary array | |
20679 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ | |
20680 constexpr bool is_binary() const noexcept | |
20681 { | |
20682 return m_data.m_type == value_t::binary; | |
20683 } | |
20684 | |
20685 /// @brief return whether value is discarded | |
20686 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ | |
20687 constexpr bool is_discarded() const noexcept | |
20688 { | |
20689 return m_data.m_type == value_t::discarded; | |
20690 } | |
20691 | |
20692 /// @brief return the type of the JSON value (implicit) | |
20693 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ | |
20694 constexpr operator value_t() const noexcept | |
20695 { | |
20696 return m_data.m_type; | |
20697 } | |
20698 | |
20699 /// @} | |
20700 | |
20701 private: | |
20702 ////////////////// | |
20703 // value access // | |
20704 ////////////////// | |
20705 | |
20706 /// get a boolean (explicit) | |
20707 boolean_t get_impl(boolean_t* /*unused*/) const | |
20708 { | |
20709 if (JSON_HEDLEY_LIKELY(is_boolean())) | |
20710 { | |
20711 return m_data.m_value.boolean; | |
20712 } | |
20713 | |
20714 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); | |
20715 } | |
20716 | |
20717 /// get a pointer to the value (object) | |
20718 object_t* get_impl_ptr(object_t* /*unused*/) noexcept | |
20719 { | |
20720 return is_object() ? m_data.m_value.object : nullptr; | |
20721 } | |
20722 | |
20723 /// get a pointer to the value (object) | |
20724 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept | |
20725 { | |
20726 return is_object() ? m_data.m_value.object : nullptr; | |
20727 } | |
20728 | |
20729 /// get a pointer to the value (array) | |
20730 array_t* get_impl_ptr(array_t* /*unused*/) noexcept | |
20731 { | |
20732 return is_array() ? m_data.m_value.array : nullptr; | |
20733 } | |
20734 | |
20735 /// get a pointer to the value (array) | |
20736 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept | |
20737 { | |
20738 return is_array() ? m_data.m_value.array : nullptr; | |
20739 } | |
20740 | |
20741 /// get a pointer to the value (string) | |
20742 string_t* get_impl_ptr(string_t* /*unused*/) noexcept | |
20743 { | |
20744 return is_string() ? m_data.m_value.string : nullptr; | |
20745 } | |
20746 | |
20747 /// get a pointer to the value (string) | |
20748 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept | |
20749 { | |
20750 return is_string() ? m_data.m_value.string : nullptr; | |
20751 } | |
20752 | |
20753 /// get a pointer to the value (boolean) | |
20754 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept | |
20755 { | |
20756 return is_boolean() ? &m_data.m_value.boolean : nullptr; | |
20757 } | |
20758 | |
20759 /// get a pointer to the value (boolean) | |
20760 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept | |
20761 { | |
20762 return is_boolean() ? &m_data.m_value.boolean : nullptr; | |
20763 } | |
20764 | |
20765 /// get a pointer to the value (integer number) | |
20766 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept | |
20767 { | |
20768 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; | |
20769 } | |
20770 | |
20771 /// get a pointer to the value (integer number) | |
20772 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept | |
20773 { | |
20774 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; | |
20775 } | |
20776 | |
20777 /// get a pointer to the value (unsigned number) | |
20778 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept | |
20779 { | |
20780 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; | |
20781 } | |
20782 | |
20783 /// get a pointer to the value (unsigned number) | |
20784 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept | |
20785 { | |
20786 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; | |
20787 } | |
20788 | |
20789 /// get a pointer to the value (floating-point number) | |
20790 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept | |
20791 { | |
20792 return is_number_float() ? &m_data.m_value.number_float : nullptr; | |
20793 } | |
20794 | |
20795 /// get a pointer to the value (floating-point number) | |
20796 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept | |
20797 { | |
20798 return is_number_float() ? &m_data.m_value.number_float : nullptr; | |
20799 } | |
20800 | |
20801 /// get a pointer to the value (binary) | |
20802 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept | |
20803 { | |
20804 return is_binary() ? m_data.m_value.binary : nullptr; | |
20805 } | |
20806 | |
20807 /// get a pointer to the value (binary) | |
20808 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept | |
20809 { | |
20810 return is_binary() ? m_data.m_value.binary : nullptr; | |
20811 } | |
20812 | |
20813 /*! | |
20814 @brief helper function to implement get_ref() | |
20815 | |
20816 This function helps to implement get_ref() without code duplication for | |
20817 const and non-const overloads | |
20818 | |
20819 @tparam ThisType will be deduced as `basic_json` or `const basic_json` | |
20820 | |
20821 @throw type_error.303 if ReferenceType does not match underlying value | |
20822 type of the current JSON | |
20823 */ | |
20824 template<typename ReferenceType, typename ThisType> | |
20825 static ReferenceType get_ref_impl(ThisType& obj) | |
20826 { | |
20827 // delegate the call to get_ptr<>() | |
20828 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); | |
20829 | |
20830 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) | |
20831 { | |
20832 return *ptr; | |
20833 } | |
20834 | |
20835 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj)); | |
20836 } | |
20837 | |
20838 public: | |
20839 /// @name value access | |
20840 /// Direct access to the stored value of a JSON value. | |
20841 /// @{ | |
20842 | |
20843 /// @brief get a pointer value (implicit) | |
20844 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ | |
20845 template<typename PointerType, typename std::enable_if< | |
20846 std::is_pointer<PointerType>::value, int>::type = 0> | |
20847 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) | |
20848 { | |
20849 // delegate the call to get_impl_ptr<>() | |
20850 return get_impl_ptr(static_cast<PointerType>(nullptr)); | |
20851 } | |
20852 | |
20853 /// @brief get a pointer value (implicit) | |
20854 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ | |
20855 template < typename PointerType, typename std::enable_if < | |
20856 std::is_pointer<PointerType>::value&& | |
20857 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 > | |
20858 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) | |
20859 { | |
20860 // delegate the call to get_impl_ptr<>() const | |
20861 return get_impl_ptr(static_cast<PointerType>(nullptr)); | |
20862 } | |
20863 | |
20864 private: | |
20865 /*! | |
20866 @brief get a value (explicit) | |
20867 | |
20868 Explicit type conversion between the JSON value and a compatible value | |
20869 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) | |
20870 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). | |
20871 The value is converted by calling the @ref json_serializer<ValueType> | |
20872 `from_json()` method. | |
20873 | |
20874 The function is equivalent to executing | |
20875 @code {.cpp} | |
20876 ValueType ret; | |
20877 JSONSerializer<ValueType>::from_json(*this, ret); | |
20878 return ret; | |
20879 @endcode | |
20880 | |
20881 This overloads is chosen if: | |
20882 - @a ValueType is not @ref basic_json, | |
20883 - @ref json_serializer<ValueType> has a `from_json()` method of the form | |
20884 `void from_json(const basic_json&, ValueType&)`, and | |
20885 - @ref json_serializer<ValueType> does not have a `from_json()` method of | |
20886 the form `ValueType from_json(const basic_json&)` | |
20887 | |
20888 @tparam ValueType the returned value type | |
20889 | |
20890 @return copy of the JSON value, converted to @a ValueType | |
20891 | |
20892 @throw what @ref json_serializer<ValueType> `from_json()` method throws | |
20893 | |
20894 @liveexample{The example below shows several conversions from JSON values | |
20895 to other types. There a few things to note: (1) Floating-point numbers can | |
20896 be converted to integers\, (2) A JSON array can be converted to a standard | |
20897 `std::vector<short>`\, (3) A JSON object can be converted to C++ | |
20898 associative containers such as `std::unordered_map<std::string\, | |
20899 json>`.,get__ValueType_const} | |
20900 | |
20901 @since version 2.1.0 | |
20902 */ | |
20903 template < typename ValueType, | |
20904 detail::enable_if_t < | |
20905 detail::is_default_constructible<ValueType>::value&& | |
20906 detail::has_from_json<basic_json_t, ValueType>::value, | |
20907 int > = 0 > | |
20908 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( | |
20909 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) | |
20910 { | |
20911 auto ret = ValueType(); | |
20912 JSONSerializer<ValueType>::from_json(*this, ret); | |
20913 return ret; | |
20914 } | |
20915 | |
20916 /*! | |
20917 @brief get a value (explicit); special case | |
20918 | |
20919 Explicit type conversion between the JSON value and a compatible value | |
20920 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) | |
20921 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). | |
20922 The value is converted by calling the @ref json_serializer<ValueType> | |
20923 `from_json()` method. | |
20924 | |
20925 The function is equivalent to executing | |
20926 @code {.cpp} | |
20927 return JSONSerializer<ValueType>::from_json(*this); | |
20928 @endcode | |
20929 | |
20930 This overloads is chosen if: | |
20931 - @a ValueType is not @ref basic_json and | |
20932 - @ref json_serializer<ValueType> has a `from_json()` method of the form | |
20933 `ValueType from_json(const basic_json&)` | |
20934 | |
20935 @note If @ref json_serializer<ValueType> has both overloads of | |
20936 `from_json()`, this one is chosen. | |
20937 | |
20938 @tparam ValueType the returned value type | |
20939 | |
20940 @return copy of the JSON value, converted to @a ValueType | |
20941 | |
20942 @throw what @ref json_serializer<ValueType> `from_json()` method throws | |
20943 | |
20944 @since version 2.1.0 | |
20945 */ | |
20946 template < typename ValueType, | |
20947 detail::enable_if_t < | |
20948 detail::has_non_default_from_json<basic_json_t, ValueType>::value, | |
20949 int > = 0 > | |
20950 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( | |
20951 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) | |
20952 { | |
20953 return JSONSerializer<ValueType>::from_json(*this); | |
20954 } | |
20955 | |
20956 /*! | |
20957 @brief get special-case overload | |
20958 | |
20959 This overloads converts the current @ref basic_json in a different | |
20960 @ref basic_json type | |
20961 | |
20962 @tparam BasicJsonType == @ref basic_json | |
20963 | |
20964 @return a copy of *this, converted into @a BasicJsonType | |
20965 | |
20966 @complexity Depending on the implementation of the called `from_json()` | |
20967 method. | |
20968 | |
20969 @since version 3.2.0 | |
20970 */ | |
20971 template < typename BasicJsonType, | |
20972 detail::enable_if_t < | |
20973 detail::is_basic_json<BasicJsonType>::value, | |
20974 int > = 0 > | |
20975 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const | |
20976 { | |
20977 return *this; | |
20978 } | |
20979 | |
20980 /*! | |
20981 @brief get special-case overload | |
20982 | |
20983 This overloads avoids a lot of template boilerplate, it can be seen as the | |
20984 identity method | |
20985 | |
20986 @tparam BasicJsonType == @ref basic_json | |
20987 | |
20988 @return a copy of *this | |
20989 | |
20990 @complexity Constant. | |
20991 | |
20992 @since version 2.1.0 | |
20993 */ | |
20994 template<typename BasicJsonType, | |
20995 detail::enable_if_t< | |
20996 std::is_same<BasicJsonType, basic_json_t>::value, | |
20997 int> = 0> | |
20998 basic_json get_impl(detail::priority_tag<3> /*unused*/) const | |
20999 { | |
21000 return *this; | |
21001 } | |
21002 | |
21003 /*! | |
21004 @brief get a pointer value (explicit) | |
21005 @copydoc get() | |
21006 */ | |
21007 template<typename PointerType, | |
21008 detail::enable_if_t< | |
21009 std::is_pointer<PointerType>::value, | |
21010 int> = 0> | |
21011 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept | |
21012 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) | |
21013 { | |
21014 // delegate the call to get_ptr | |
21015 return get_ptr<PointerType>(); | |
21016 } | |
21017 | |
21018 public: | |
21019 /*! | |
21020 @brief get a (pointer) value (explicit) | |
21021 | |
21022 Performs explicit type conversion between the JSON value and a compatible value if required. | |
21023 | |
21024 - If the requested type is a pointer to the internally stored JSON value that pointer is returned. | |
21025 No copies are made. | |
21026 | |
21027 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible | |
21028 from the current @ref basic_json. | |
21029 | |
21030 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` | |
21031 method. | |
21032 | |
21033 @tparam ValueTypeCV the provided value type | |
21034 @tparam ValueType the returned value type | |
21035 | |
21036 @return copy of the JSON value, converted to @tparam ValueType if necessary | |
21037 | |
21038 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required | |
21039 | |
21040 @since version 2.1.0 | |
21041 */ | |
21042 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>> | |
21043 #if defined(JSON_HAS_CPP_14) | |
21044 constexpr | |
21045 #endif | |
21046 auto get() const noexcept( | |
21047 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))) | |
21048 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) | |
21049 { | |
21050 // we cannot static_assert on ValueTypeCV being non-const, because | |
21051 // there is support for get<const basic_json_t>(), which is why we | |
21052 // still need the uncvref | |
21053 static_assert(!std::is_reference<ValueTypeCV>::value, | |
21054 "get() cannot be used with reference types, you might want to use get_ref()"); | |
21055 return get_impl<ValueType>(detail::priority_tag<4> {}); | |
21056 } | |
21057 | |
21058 /*! | |
21059 @brief get a pointer value (explicit) | |
21060 | |
21061 Explicit pointer access to the internally stored JSON value. No copies are | |
21062 made. | |
21063 | |
21064 @warning The pointer becomes invalid if the underlying JSON object | |
21065 changes. | |
21066 | |
21067 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref | |
21068 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, | |
21069 @ref number_unsigned_t, or @ref number_float_t. | |
21070 | |
21071 @return pointer to the internally stored JSON value if the requested | |
21072 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise | |
21073 | |
21074 @complexity Constant. | |
21075 | |
21076 @liveexample{The example below shows how pointers to internal values of a | |
21077 JSON value can be requested. Note that no type conversions are made and a | |
21078 `nullptr` is returned if the value and the requested pointer type does not | |
21079 match.,get__PointerType} | |
21080 | |
21081 @sa see @ref get_ptr() for explicit pointer-member access | |
21082 | |
21083 @since version 1.0.0 | |
21084 */ | |
21085 template<typename PointerType, typename std::enable_if< | |
21086 std::is_pointer<PointerType>::value, int>::type = 0> | |
21087 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) | |
21088 { | |
21089 // delegate the call to get_ptr | |
21090 return get_ptr<PointerType>(); | |
21091 } | |
21092 | |
21093 /// @brief get a value (explicit) | |
21094 /// @sa https://json.nlohmann.me/api/basic_json/get_to/ | |
21095 template < typename ValueType, | |
21096 detail::enable_if_t < | |
21097 !detail::is_basic_json<ValueType>::value&& | |
21098 detail::has_from_json<basic_json_t, ValueType>::value, | |
21099 int > = 0 > | |
21100 ValueType & get_to(ValueType& v) const noexcept(noexcept( | |
21101 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) | |
21102 { | |
21103 JSONSerializer<ValueType>::from_json(*this, v); | |
21104 return v; | |
21105 } | |
21106 | |
21107 // specialization to allow calling get_to with a basic_json value | |
21108 // see https://github.com/nlohmann/json/issues/2175 | |
21109 template<typename ValueType, | |
21110 detail::enable_if_t < | |
21111 detail::is_basic_json<ValueType>::value, | |
21112 int> = 0> | |
21113 ValueType & get_to(ValueType& v) const | |
21114 { | |
21115 v = *this; | |
21116 return v; | |
21117 } | |
21118 | |
21119 template < | |
21120 typename T, std::size_t N, | |
21121 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
21122 detail::enable_if_t < | |
21123 detail::has_from_json<basic_json_t, Array>::value, int > = 0 > | |
21124 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) | |
21125 noexcept(noexcept(JSONSerializer<Array>::from_json( | |
21126 std::declval<const basic_json_t&>(), v))) | |
21127 { | |
21128 JSONSerializer<Array>::from_json(*this, v); | |
21129 return v; | |
21130 } | |
21131 | |
21132 /// @brief get a reference value (implicit) | |
21133 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ | |
21134 template<typename ReferenceType, typename std::enable_if< | |
21135 std::is_reference<ReferenceType>::value, int>::type = 0> | |
21136 ReferenceType get_ref() | |
21137 { | |
21138 // delegate call to get_ref_impl | |
21139 return get_ref_impl<ReferenceType>(*this); | |
21140 } | |
21141 | |
21142 /// @brief get a reference value (implicit) | |
21143 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ | |
21144 template < typename ReferenceType, typename std::enable_if < | |
21145 std::is_reference<ReferenceType>::value&& | |
21146 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 > | |
21147 ReferenceType get_ref() const | |
21148 { | |
21149 // delegate call to get_ref_impl | |
21150 return get_ref_impl<ReferenceType>(*this); | |
21151 } | |
21152 | |
21153 /*! | |
21154 @brief get a value (implicit) | |
21155 | |
21156 Implicit type conversion between the JSON value and a compatible value. | |
21157 The call is realized by calling @ref get() const. | |
21158 | |
21159 @tparam ValueType non-pointer type compatible to the JSON value, for | |
21160 instance `int` for JSON integer numbers, `bool` for JSON booleans, or | |
21161 `std::vector` types for JSON arrays. The character type of @ref string_t | |
21162 as well as an initializer list of this type is excluded to avoid | |
21163 ambiguities as these types implicitly convert to `std::string`. | |
21164 | |
21165 @return copy of the JSON value, converted to type @a ValueType | |
21166 | |
21167 @throw type_error.302 in case passed type @a ValueType is incompatible | |
21168 to the JSON value type (e.g., the JSON value is of type boolean, but a | |
21169 string is requested); see example below | |
21170 | |
21171 @complexity Linear in the size of the JSON value. | |
21172 | |
21173 @liveexample{The example below shows several conversions from JSON values | |
21174 to other types. There a few things to note: (1) Floating-point numbers can | |
21175 be converted to integers\, (2) A JSON array can be converted to a standard | |
21176 `std::vector<short>`\, (3) A JSON object can be converted to C++ | |
21177 associative containers such as `std::unordered_map<std::string\, | |
21178 json>`.,operator__ValueType} | |
21179 | |
21180 @since version 1.0.0 | |
21181 */ | |
21182 template < typename ValueType, typename std::enable_if < | |
21183 detail::conjunction < | |
21184 detail::negation<std::is_pointer<ValueType>>, | |
21185 detail::negation<std::is_same<ValueType, std::nullptr_t>>, | |
21186 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, | |
21187 detail::negation<std::is_same<ValueType, typename string_t::value_type>>, | |
21188 detail::negation<detail::is_basic_json<ValueType>>, | |
21189 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>, | |
21190 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) | |
21191 detail::negation<std::is_same<ValueType, std::string_view>>, | |
21192 #endif | |
21193 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI | |
21194 detail::negation<std::is_same<ValueType, std::any>>, | |
21195 #endif | |
21196 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType> | |
21197 >::value, int >::type = 0 > | |
21198 JSON_EXPLICIT operator ValueType() const | |
21199 { | |
21200 // delegate the call to get<>() const | |
21201 return get<ValueType>(); | |
21202 } | |
21203 | |
21204 /// @brief get a binary value | |
21205 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ | |
21206 binary_t& get_binary() | |
21207 { | |
21208 if (!is_binary()) | |
21209 { | |
21210 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); | |
21211 } | |
21212 | |
21213 return *get_ptr<binary_t*>(); | |
21214 } | |
21215 | |
21216 /// @brief get a binary value | |
21217 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ | |
21218 const binary_t& get_binary() const | |
21219 { | |
21220 if (!is_binary()) | |
21221 { | |
21222 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); | |
21223 } | |
21224 | |
21225 return *get_ptr<const binary_t*>(); | |
21226 } | |
21227 | |
21228 /// @} | |
21229 | |
21230 //////////////////// | |
21231 // element access // | |
21232 //////////////////// | |
21233 | |
21234 /// @name element access | |
21235 /// Access to the JSON value. | |
21236 /// @{ | |
21237 | |
21238 /// @brief access specified array element with bounds checking | |
21239 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21240 reference at(size_type idx) | |
21241 { | |
21242 // at only works for arrays | |
21243 if (JSON_HEDLEY_LIKELY(is_array())) | |
21244 { | |
21245 JSON_TRY | |
21246 { | |
21247 return set_parent(m_data.m_value.array->at(idx)); | |
21248 } | |
21249 JSON_CATCH (std::out_of_range&) | |
21250 { | |
21251 // create better exception explanation | |
21252 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); | |
21253 } | |
21254 } | |
21255 else | |
21256 { | |
21257 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21258 } | |
21259 } | |
21260 | |
21261 /// @brief access specified array element with bounds checking | |
21262 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21263 const_reference at(size_type idx) const | |
21264 { | |
21265 // at only works for arrays | |
21266 if (JSON_HEDLEY_LIKELY(is_array())) | |
21267 { | |
21268 JSON_TRY | |
21269 { | |
21270 return m_data.m_value.array->at(idx); | |
21271 } | |
21272 JSON_CATCH (std::out_of_range&) | |
21273 { | |
21274 // create better exception explanation | |
21275 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); | |
21276 } | |
21277 } | |
21278 else | |
21279 { | |
21280 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21281 } | |
21282 } | |
21283 | |
21284 /// @brief access specified object element with bounds checking | |
21285 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21286 reference at(const typename object_t::key_type& key) | |
21287 { | |
21288 // at only works for objects | |
21289 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21290 { | |
21291 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21292 } | |
21293 | |
21294 auto it = m_data.m_value.object->find(key); | |
21295 if (it == m_data.m_value.object->end()) | |
21296 { | |
21297 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); | |
21298 } | |
21299 return set_parent(it->second); | |
21300 } | |
21301 | |
21302 /// @brief access specified object element with bounds checking | |
21303 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21304 template<class KeyType, detail::enable_if_t< | |
21305 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
21306 reference at(KeyType && key) | |
21307 { | |
21308 // at only works for objects | |
21309 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21310 { | |
21311 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21312 } | |
21313 | |
21314 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
21315 if (it == m_data.m_value.object->end()) | |
21316 { | |
21317 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); | |
21318 } | |
21319 return set_parent(it->second); | |
21320 } | |
21321 | |
21322 /// @brief access specified object element with bounds checking | |
21323 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21324 const_reference at(const typename object_t::key_type& key) const | |
21325 { | |
21326 // at only works for objects | |
21327 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21328 { | |
21329 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21330 } | |
21331 | |
21332 auto it = m_data.m_value.object->find(key); | |
21333 if (it == m_data.m_value.object->end()) | |
21334 { | |
21335 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); | |
21336 } | |
21337 return it->second; | |
21338 } | |
21339 | |
21340 /// @brief access specified object element with bounds checking | |
21341 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
21342 template<class KeyType, detail::enable_if_t< | |
21343 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
21344 const_reference at(KeyType && key) const | |
21345 { | |
21346 // at only works for objects | |
21347 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21348 { | |
21349 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); | |
21350 } | |
21351 | |
21352 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
21353 if (it == m_data.m_value.object->end()) | |
21354 { | |
21355 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); | |
21356 } | |
21357 return it->second; | |
21358 } | |
21359 | |
21360 /// @brief access specified array element | |
21361 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21362 reference operator[](size_type idx) | |
21363 { | |
21364 // implicitly convert null value to an empty array | |
21365 if (is_null()) | |
21366 { | |
21367 m_data.m_type = value_t::array; | |
21368 m_data.m_value.array = create<array_t>(); | |
21369 assert_invariant(); | |
21370 } | |
21371 | |
21372 // operator[] only works for arrays | |
21373 if (JSON_HEDLEY_LIKELY(is_array())) | |
21374 { | |
21375 // fill up array with null values if given idx is outside range | |
21376 if (idx >= m_data.m_value.array->size()) | |
21377 { | |
21378 #if JSON_DIAGNOSTICS | |
21379 // remember array size & capacity before resizing | |
21380 const auto old_size = m_data.m_value.array->size(); | |
21381 const auto old_capacity = m_data.m_value.array->capacity(); | |
21382 #endif | |
21383 m_data.m_value.array->resize(idx + 1); | |
21384 | |
21385 #if JSON_DIAGNOSTICS | |
21386 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) | |
21387 { | |
21388 // capacity has changed: update all parents | |
21389 set_parents(); | |
21390 } | |
21391 else | |
21392 { | |
21393 // set parent for values added above | |
21394 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size)); | |
21395 } | |
21396 #endif | |
21397 assert_invariant(); | |
21398 } | |
21399 | |
21400 return m_data.m_value.array->operator[](idx); | |
21401 } | |
21402 | |
21403 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); | |
21404 } | |
21405 | |
21406 /// @brief access specified array element | |
21407 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21408 const_reference operator[](size_type idx) const | |
21409 { | |
21410 // const operator[] only works for arrays | |
21411 if (JSON_HEDLEY_LIKELY(is_array())) | |
21412 { | |
21413 return m_data.m_value.array->operator[](idx); | |
21414 } | |
21415 | |
21416 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); | |
21417 } | |
21418 | |
21419 /// @brief access specified object element | |
21420 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21421 reference operator[](typename object_t::key_type key) | |
21422 { | |
21423 // implicitly convert null value to an empty object | |
21424 if (is_null()) | |
21425 { | |
21426 m_data.m_type = value_t::object; | |
21427 m_data.m_value.object = create<object_t>(); | |
21428 assert_invariant(); | |
21429 } | |
21430 | |
21431 // operator[] only works for objects | |
21432 if (JSON_HEDLEY_LIKELY(is_object())) | |
21433 { | |
21434 auto result = m_data.m_value.object->emplace(std::move(key), nullptr); | |
21435 return set_parent(result.first->second); | |
21436 } | |
21437 | |
21438 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); | |
21439 } | |
21440 | |
21441 /// @brief access specified object element | |
21442 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21443 const_reference operator[](const typename object_t::key_type& key) const | |
21444 { | |
21445 // const operator[] only works for objects | |
21446 if (JSON_HEDLEY_LIKELY(is_object())) | |
21447 { | |
21448 auto it = m_data.m_value.object->find(key); | |
21449 JSON_ASSERT(it != m_data.m_value.object->end()); | |
21450 return it->second; | |
21451 } | |
21452 | |
21453 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); | |
21454 } | |
21455 | |
21456 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC | |
21457 // (they seemingly cannot be constrained to resolve the ambiguity) | |
21458 template<typename T> | |
21459 reference operator[](T* key) | |
21460 { | |
21461 return operator[](typename object_t::key_type(key)); | |
21462 } | |
21463 | |
21464 template<typename T> | |
21465 const_reference operator[](T* key) const | |
21466 { | |
21467 return operator[](typename object_t::key_type(key)); | |
21468 } | |
21469 | |
21470 /// @brief access specified object element | |
21471 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21472 template<class KeyType, detail::enable_if_t< | |
21473 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > | |
21474 reference operator[](KeyType && key) | |
21475 { | |
21476 // implicitly convert null value to an empty object | |
21477 if (is_null()) | |
21478 { | |
21479 m_data.m_type = value_t::object; | |
21480 m_data.m_value.object = create<object_t>(); | |
21481 assert_invariant(); | |
21482 } | |
21483 | |
21484 // operator[] only works for objects | |
21485 if (JSON_HEDLEY_LIKELY(is_object())) | |
21486 { | |
21487 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr); | |
21488 return set_parent(result.first->second); | |
21489 } | |
21490 | |
21491 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); | |
21492 } | |
21493 | |
21494 /// @brief access specified object element | |
21495 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
21496 template<class KeyType, detail::enable_if_t< | |
21497 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > | |
21498 const_reference operator[](KeyType && key) const | |
21499 { | |
21500 // const operator[] only works for objects | |
21501 if (JSON_HEDLEY_LIKELY(is_object())) | |
21502 { | |
21503 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
21504 JSON_ASSERT(it != m_data.m_value.object->end()); | |
21505 return it->second; | |
21506 } | |
21507 | |
21508 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); | |
21509 } | |
21510 | |
21511 private: | |
21512 template<typename KeyType> | |
21513 using is_comparable_with_object_key = detail::is_comparable < | |
21514 object_comparator_t, const typename object_t::key_type&, KeyType >; | |
21515 | |
21516 template<typename ValueType> | |
21517 using value_return_type = std::conditional < | |
21518 detail::is_c_string_uncvref<ValueType>::value, | |
21519 string_t, typename std::decay<ValueType>::type >; | |
21520 | |
21521 public: | |
21522 /// @brief access specified object element with default value | |
21523 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21524 template < class ValueType, detail::enable_if_t < | |
21525 !detail::is_transparent<object_comparator_t>::value | |
21526 && detail::is_getable<basic_json_t, ValueType>::value | |
21527 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21528 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const | |
21529 { | |
21530 // value only works for objects | |
21531 if (JSON_HEDLEY_LIKELY(is_object())) | |
21532 { | |
21533 // if key is found, return value and given default value otherwise | |
21534 const auto it = find(key); | |
21535 if (it != end()) | |
21536 { | |
21537 return it->template get<ValueType>(); | |
21538 } | |
21539 | |
21540 return default_value; | |
21541 } | |
21542 | |
21543 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21544 } | |
21545 | |
21546 /// @brief access specified object element with default value | |
21547 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21548 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, | |
21549 detail::enable_if_t < | |
21550 !detail::is_transparent<object_comparator_t>::value | |
21551 && detail::is_getable<basic_json_t, ReturnType>::value | |
21552 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21553 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const | |
21554 { | |
21555 // value only works for objects | |
21556 if (JSON_HEDLEY_LIKELY(is_object())) | |
21557 { | |
21558 // if key is found, return value and given default value otherwise | |
21559 const auto it = find(key); | |
21560 if (it != end()) | |
21561 { | |
21562 return it->template get<ReturnType>(); | |
21563 } | |
21564 | |
21565 return std::forward<ValueType>(default_value); | |
21566 } | |
21567 | |
21568 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21569 } | |
21570 | |
21571 /// @brief access specified object element with default value | |
21572 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21573 template < class ValueType, class KeyType, detail::enable_if_t < | |
21574 detail::is_transparent<object_comparator_t>::value | |
21575 && !detail::is_json_pointer<KeyType>::value | |
21576 && is_comparable_with_object_key<KeyType>::value | |
21577 && detail::is_getable<basic_json_t, ValueType>::value | |
21578 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21579 ValueType value(KeyType && key, const ValueType& default_value) const | |
21580 { | |
21581 // value only works for objects | |
21582 if (JSON_HEDLEY_LIKELY(is_object())) | |
21583 { | |
21584 // if key is found, return value and given default value otherwise | |
21585 const auto it = find(std::forward<KeyType>(key)); | |
21586 if (it != end()) | |
21587 { | |
21588 return it->template get<ValueType>(); | |
21589 } | |
21590 | |
21591 return default_value; | |
21592 } | |
21593 | |
21594 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21595 } | |
21596 | |
21597 /// @brief access specified object element via JSON Pointer with default value | |
21598 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21599 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type, | |
21600 detail::enable_if_t < | |
21601 detail::is_transparent<object_comparator_t>::value | |
21602 && !detail::is_json_pointer<KeyType>::value | |
21603 && is_comparable_with_object_key<KeyType>::value | |
21604 && detail::is_getable<basic_json_t, ReturnType>::value | |
21605 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21606 ReturnType value(KeyType && key, ValueType && default_value) const | |
21607 { | |
21608 // value only works for objects | |
21609 if (JSON_HEDLEY_LIKELY(is_object())) | |
21610 { | |
21611 // if key is found, return value and given default value otherwise | |
21612 const auto it = find(std::forward<KeyType>(key)); | |
21613 if (it != end()) | |
21614 { | |
21615 return it->template get<ReturnType>(); | |
21616 } | |
21617 | |
21618 return std::forward<ValueType>(default_value); | |
21619 } | |
21620 | |
21621 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21622 } | |
21623 | |
21624 /// @brief access specified object element via JSON Pointer with default value | |
21625 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21626 template < class ValueType, detail::enable_if_t < | |
21627 detail::is_getable<basic_json_t, ValueType>::value | |
21628 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21629 ValueType value(const json_pointer& ptr, const ValueType& default_value) const | |
21630 { | |
21631 // value only works for objects | |
21632 if (JSON_HEDLEY_LIKELY(is_object())) | |
21633 { | |
21634 // if pointer resolves a value, return it or use default value | |
21635 JSON_TRY | |
21636 { | |
21637 return ptr.get_checked(this).template get<ValueType>(); | |
21638 } | |
21639 JSON_INTERNAL_CATCH (out_of_range&) | |
21640 { | |
21641 return default_value; | |
21642 } | |
21643 } | |
21644 | |
21645 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21646 } | |
21647 | |
21648 /// @brief access specified object element via JSON Pointer with default value | |
21649 /// @sa https://json.nlohmann.me/api/basic_json/value/ | |
21650 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, | |
21651 detail::enable_if_t < | |
21652 detail::is_getable<basic_json_t, ReturnType>::value | |
21653 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21654 ReturnType value(const json_pointer& ptr, ValueType && default_value) const | |
21655 { | |
21656 // value only works for objects | |
21657 if (JSON_HEDLEY_LIKELY(is_object())) | |
21658 { | |
21659 // if pointer resolves a value, return it or use default value | |
21660 JSON_TRY | |
21661 { | |
21662 return ptr.get_checked(this).template get<ReturnType>(); | |
21663 } | |
21664 JSON_INTERNAL_CATCH (out_of_range&) | |
21665 { | |
21666 return std::forward<ValueType>(default_value); | |
21667 } | |
21668 } | |
21669 | |
21670 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); | |
21671 } | |
21672 | |
21673 template < class ValueType, class BasicJsonType, detail::enable_if_t < | |
21674 detail::is_basic_json<BasicJsonType>::value | |
21675 && detail::is_getable<basic_json_t, ValueType>::value | |
21676 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21677 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
21678 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const | |
21679 { | |
21680 return value(ptr.convert(), default_value); | |
21681 } | |
21682 | |
21683 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, | |
21684 detail::enable_if_t < | |
21685 detail::is_basic_json<BasicJsonType>::value | |
21686 && detail::is_getable<basic_json_t, ReturnType>::value | |
21687 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > | |
21688 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
21689 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const | |
21690 { | |
21691 return value(ptr.convert(), std::forward<ValueType>(default_value)); | |
21692 } | |
21693 | |
21694 /// @brief access the first element | |
21695 /// @sa https://json.nlohmann.me/api/basic_json/front/ | |
21696 reference front() | |
21697 { | |
21698 return *begin(); | |
21699 } | |
21700 | |
21701 /// @brief access the first element | |
21702 /// @sa https://json.nlohmann.me/api/basic_json/front/ | |
21703 const_reference front() const | |
21704 { | |
21705 return *cbegin(); | |
21706 } | |
21707 | |
21708 /// @brief access the last element | |
21709 /// @sa https://json.nlohmann.me/api/basic_json/back/ | |
21710 reference back() | |
21711 { | |
21712 auto tmp = end(); | |
21713 --tmp; | |
21714 return *tmp; | |
21715 } | |
21716 | |
21717 /// @brief access the last element | |
21718 /// @sa https://json.nlohmann.me/api/basic_json/back/ | |
21719 const_reference back() const | |
21720 { | |
21721 auto tmp = cend(); | |
21722 --tmp; | |
21723 return *tmp; | |
21724 } | |
21725 | |
21726 /// @brief remove element given an iterator | |
21727 /// @sa https://json.nlohmann.me/api/basic_json/erase/ | |
21728 template < class IteratorType, detail::enable_if_t < | |
21729 std::is_same<IteratorType, typename basic_json_t::iterator>::value || | |
21730 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > | |
21731 IteratorType erase(IteratorType pos) | |
21732 { | |
21733 // make sure iterator fits the current value | |
21734 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) | |
21735 { | |
21736 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); | |
21737 } | |
21738 | |
21739 IteratorType result = end(); | |
21740 | |
21741 switch (m_data.m_type) | |
21742 { | |
21743 case value_t::boolean: | |
21744 case value_t::number_float: | |
21745 case value_t::number_integer: | |
21746 case value_t::number_unsigned: | |
21747 case value_t::string: | |
21748 case value_t::binary: | |
21749 { | |
21750 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) | |
21751 { | |
21752 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this)); | |
21753 } | |
21754 | |
21755 if (is_string()) | |
21756 { | |
21757 AllocatorType<string_t> alloc; | |
21758 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); | |
21759 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); | |
21760 m_data.m_value.string = nullptr; | |
21761 } | |
21762 else if (is_binary()) | |
21763 { | |
21764 AllocatorType<binary_t> alloc; | |
21765 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); | |
21766 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); | |
21767 m_data.m_value.binary = nullptr; | |
21768 } | |
21769 | |
21770 m_data.m_type = value_t::null; | |
21771 assert_invariant(); | |
21772 break; | |
21773 } | |
21774 | |
21775 case value_t::object: | |
21776 { | |
21777 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); | |
21778 break; | |
21779 } | |
21780 | |
21781 case value_t::array: | |
21782 { | |
21783 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); | |
21784 break; | |
21785 } | |
21786 | |
21787 case value_t::null: | |
21788 case value_t::discarded: | |
21789 default: | |
21790 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); | |
21791 } | |
21792 | |
21793 return result; | |
21794 } | |
21795 | |
21796 /// @brief remove elements given an iterator range | |
21797 /// @sa https://json.nlohmann.me/api/basic_json/erase/ | |
21798 template < class IteratorType, detail::enable_if_t < | |
21799 std::is_same<IteratorType, typename basic_json_t::iterator>::value || | |
21800 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > | |
21801 IteratorType erase(IteratorType first, IteratorType last) | |
21802 { | |
21803 // make sure iterator fits the current value | |
21804 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) | |
21805 { | |
21806 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this)); | |
21807 } | |
21808 | |
21809 IteratorType result = end(); | |
21810 | |
21811 switch (m_data.m_type) | |
21812 { | |
21813 case value_t::boolean: | |
21814 case value_t::number_float: | |
21815 case value_t::number_integer: | |
21816 case value_t::number_unsigned: | |
21817 case value_t::string: | |
21818 case value_t::binary: | |
21819 { | |
21820 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() | |
21821 || !last.m_it.primitive_iterator.is_end())) | |
21822 { | |
21823 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this)); | |
21824 } | |
21825 | |
21826 if (is_string()) | |
21827 { | |
21828 AllocatorType<string_t> alloc; | |
21829 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); | |
21830 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); | |
21831 m_data.m_value.string = nullptr; | |
21832 } | |
21833 else if (is_binary()) | |
21834 { | |
21835 AllocatorType<binary_t> alloc; | |
21836 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); | |
21837 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); | |
21838 m_data.m_value.binary = nullptr; | |
21839 } | |
21840 | |
21841 m_data.m_type = value_t::null; | |
21842 assert_invariant(); | |
21843 break; | |
21844 } | |
21845 | |
21846 case value_t::object: | |
21847 { | |
21848 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, | |
21849 last.m_it.object_iterator); | |
21850 break; | |
21851 } | |
21852 | |
21853 case value_t::array: | |
21854 { | |
21855 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, | |
21856 last.m_it.array_iterator); | |
21857 break; | |
21858 } | |
21859 | |
21860 case value_t::null: | |
21861 case value_t::discarded: | |
21862 default: | |
21863 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); | |
21864 } | |
21865 | |
21866 return result; | |
21867 } | |
21868 | |
21869 private: | |
21870 template < typename KeyType, detail::enable_if_t < | |
21871 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > | |
21872 size_type erase_internal(KeyType && key) | |
21873 { | |
21874 // this erase only works for objects | |
21875 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21876 { | |
21877 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); | |
21878 } | |
21879 | |
21880 return m_data.m_value.object->erase(std::forward<KeyType>(key)); | |
21881 } | |
21882 | |
21883 template < typename KeyType, detail::enable_if_t < | |
21884 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > | |
21885 size_type erase_internal(KeyType && key) | |
21886 { | |
21887 // this erase only works for objects | |
21888 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
21889 { | |
21890 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); | |
21891 } | |
21892 | |
21893 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
21894 if (it != m_data.m_value.object->end()) | |
21895 { | |
21896 m_data.m_value.object->erase(it); | |
21897 return 1; | |
21898 } | |
21899 return 0; | |
21900 } | |
21901 | |
21902 public: | |
21903 | |
21904 /// @brief remove element from a JSON object given a key | |
21905 /// @sa https://json.nlohmann.me/api/basic_json/erase/ | |
21906 size_type erase(const typename object_t::key_type& key) | |
21907 { | |
21908 // the indirection via erase_internal() is added to avoid making this | |
21909 // function a template and thus de-rank it during overload resolution | |
21910 return erase_internal(key); | |
21911 } | |
21912 | |
21913 /// @brief remove element from a JSON object given a key | |
21914 /// @sa https://json.nlohmann.me/api/basic_json/erase/ | |
21915 template<class KeyType, detail::enable_if_t< | |
21916 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
21917 size_type erase(KeyType && key) | |
21918 { | |
21919 return erase_internal(std::forward<KeyType>(key)); | |
21920 } | |
21921 | |
21922 /// @brief remove element from a JSON array given an index | |
21923 /// @sa https://json.nlohmann.me/api/basic_json/erase/ | |
21924 void erase(const size_type idx) | |
21925 { | |
21926 // this erase only works for arrays | |
21927 if (JSON_HEDLEY_LIKELY(is_array())) | |
21928 { | |
21929 if (JSON_HEDLEY_UNLIKELY(idx >= size())) | |
21930 { | |
21931 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); | |
21932 } | |
21933 | |
21934 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx)); | |
21935 } | |
21936 else | |
21937 { | |
21938 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); | |
21939 } | |
21940 } | |
21941 | |
21942 /// @} | |
21943 | |
21944 //////////// | |
21945 // lookup // | |
21946 //////////// | |
21947 | |
21948 /// @name lookup | |
21949 /// @{ | |
21950 | |
21951 /// @brief find an element in a JSON object | |
21952 /// @sa https://json.nlohmann.me/api/basic_json/find/ | |
21953 iterator find(const typename object_t::key_type& key) | |
21954 { | |
21955 auto result = end(); | |
21956 | |
21957 if (is_object()) | |
21958 { | |
21959 result.m_it.object_iterator = m_data.m_value.object->find(key); | |
21960 } | |
21961 | |
21962 return result; | |
21963 } | |
21964 | |
21965 /// @brief find an element in a JSON object | |
21966 /// @sa https://json.nlohmann.me/api/basic_json/find/ | |
21967 const_iterator find(const typename object_t::key_type& key) const | |
21968 { | |
21969 auto result = cend(); | |
21970 | |
21971 if (is_object()) | |
21972 { | |
21973 result.m_it.object_iterator = m_data.m_value.object->find(key); | |
21974 } | |
21975 | |
21976 return result; | |
21977 } | |
21978 | |
21979 /// @brief find an element in a JSON object | |
21980 /// @sa https://json.nlohmann.me/api/basic_json/find/ | |
21981 template<class KeyType, detail::enable_if_t< | |
21982 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
21983 iterator find(KeyType && key) | |
21984 { | |
21985 auto result = end(); | |
21986 | |
21987 if (is_object()) | |
21988 { | |
21989 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
21990 } | |
21991 | |
21992 return result; | |
21993 } | |
21994 | |
21995 /// @brief find an element in a JSON object | |
21996 /// @sa https://json.nlohmann.me/api/basic_json/find/ | |
21997 template<class KeyType, detail::enable_if_t< | |
21998 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
21999 const_iterator find(KeyType && key) const | |
22000 { | |
22001 auto result = cend(); | |
22002 | |
22003 if (is_object()) | |
22004 { | |
22005 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); | |
22006 } | |
22007 | |
22008 return result; | |
22009 } | |
22010 | |
22011 /// @brief returns the number of occurrences of a key in a JSON object | |
22012 /// @sa https://json.nlohmann.me/api/basic_json/count/ | |
22013 size_type count(const typename object_t::key_type& key) const | |
22014 { | |
22015 // return 0 for all nonobject types | |
22016 return is_object() ? m_data.m_value.object->count(key) : 0; | |
22017 } | |
22018 | |
22019 /// @brief returns the number of occurrences of a key in a JSON object | |
22020 /// @sa https://json.nlohmann.me/api/basic_json/count/ | |
22021 template<class KeyType, detail::enable_if_t< | |
22022 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
22023 size_type count(KeyType && key) const | |
22024 { | |
22025 // return 0 for all nonobject types | |
22026 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0; | |
22027 } | |
22028 | |
22029 /// @brief check the existence of an element in a JSON object | |
22030 /// @sa https://json.nlohmann.me/api/basic_json/contains/ | |
22031 bool contains(const typename object_t::key_type& key) const | |
22032 { | |
22033 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); | |
22034 } | |
22035 | |
22036 /// @brief check the existence of an element in a JSON object | |
22037 /// @sa https://json.nlohmann.me/api/basic_json/contains/ | |
22038 template<class KeyType, detail::enable_if_t< | |
22039 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> | |
22040 bool contains(KeyType && key) const | |
22041 { | |
22042 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end(); | |
22043 } | |
22044 | |
22045 /// @brief check the existence of an element in a JSON object given a JSON pointer | |
22046 /// @sa https://json.nlohmann.me/api/basic_json/contains/ | |
22047 bool contains(const json_pointer& ptr) const | |
22048 { | |
22049 return ptr.contains(this); | |
22050 } | |
22051 | |
22052 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> | |
22053 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
22054 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const | |
22055 { | |
22056 return ptr.contains(this); | |
22057 } | |
22058 | |
22059 /// @} | |
22060 | |
22061 /////////////// | |
22062 // iterators // | |
22063 /////////////// | |
22064 | |
22065 /// @name iterators | |
22066 /// @{ | |
22067 | |
22068 /// @brief returns an iterator to the first element | |
22069 /// @sa https://json.nlohmann.me/api/basic_json/begin/ | |
22070 iterator begin() noexcept | |
22071 { | |
22072 iterator result(this); | |
22073 result.set_begin(); | |
22074 return result; | |
22075 } | |
22076 | |
22077 /// @brief returns an iterator to the first element | |
22078 /// @sa https://json.nlohmann.me/api/basic_json/begin/ | |
22079 const_iterator begin() const noexcept | |
22080 { | |
22081 return cbegin(); | |
22082 } | |
22083 | |
22084 /// @brief returns a const iterator to the first element | |
22085 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ | |
22086 const_iterator cbegin() const noexcept | |
22087 { | |
22088 const_iterator result(this); | |
22089 result.set_begin(); | |
22090 return result; | |
22091 } | |
22092 | |
22093 /// @brief returns an iterator to one past the last element | |
22094 /// @sa https://json.nlohmann.me/api/basic_json/end/ | |
22095 iterator end() noexcept | |
22096 { | |
22097 iterator result(this); | |
22098 result.set_end(); | |
22099 return result; | |
22100 } | |
22101 | |
22102 /// @brief returns an iterator to one past the last element | |
22103 /// @sa https://json.nlohmann.me/api/basic_json/end/ | |
22104 const_iterator end() const noexcept | |
22105 { | |
22106 return cend(); | |
22107 } | |
22108 | |
22109 /// @brief returns an iterator to one past the last element | |
22110 /// @sa https://json.nlohmann.me/api/basic_json/cend/ | |
22111 const_iterator cend() const noexcept | |
22112 { | |
22113 const_iterator result(this); | |
22114 result.set_end(); | |
22115 return result; | |
22116 } | |
22117 | |
22118 /// @brief returns an iterator to the reverse-beginning | |
22119 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ | |
22120 reverse_iterator rbegin() noexcept | |
22121 { | |
22122 return reverse_iterator(end()); | |
22123 } | |
22124 | |
22125 /// @brief returns an iterator to the reverse-beginning | |
22126 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ | |
22127 const_reverse_iterator rbegin() const noexcept | |
22128 { | |
22129 return crbegin(); | |
22130 } | |
22131 | |
22132 /// @brief returns an iterator to the reverse-end | |
22133 /// @sa https://json.nlohmann.me/api/basic_json/rend/ | |
22134 reverse_iterator rend() noexcept | |
22135 { | |
22136 return reverse_iterator(begin()); | |
22137 } | |
22138 | |
22139 /// @brief returns an iterator to the reverse-end | |
22140 /// @sa https://json.nlohmann.me/api/basic_json/rend/ | |
22141 const_reverse_iterator rend() const noexcept | |
22142 { | |
22143 return crend(); | |
22144 } | |
22145 | |
22146 /// @brief returns a const reverse iterator to the last element | |
22147 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ | |
22148 const_reverse_iterator crbegin() const noexcept | |
22149 { | |
22150 return const_reverse_iterator(cend()); | |
22151 } | |
22152 | |
22153 /// @brief returns a const reverse iterator to one before the first | |
22154 /// @sa https://json.nlohmann.me/api/basic_json/crend/ | |
22155 const_reverse_iterator crend() const noexcept | |
22156 { | |
22157 return const_reverse_iterator(cbegin()); | |
22158 } | |
22159 | |
22160 public: | |
22161 /// @brief wrapper to access iterator member functions in range-based for | |
22162 /// @sa https://json.nlohmann.me/api/basic_json/items/ | |
22163 /// @deprecated This function is deprecated since 3.1.0 and will be removed in | |
22164 /// version 4.0.0 of the library. Please use @ref items() instead; | |
22165 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. | |
22166 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) | |
22167 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept | |
22168 { | |
22169 return ref.items(); | |
22170 } | |
22171 | |
22172 /// @brief wrapper to access iterator member functions in range-based for | |
22173 /// @sa https://json.nlohmann.me/api/basic_json/items/ | |
22174 /// @deprecated This function is deprecated since 3.1.0 and will be removed in | |
22175 /// version 4.0.0 of the library. Please use @ref items() instead; | |
22176 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. | |
22177 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) | |
22178 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept | |
22179 { | |
22180 return ref.items(); | |
22181 } | |
22182 | |
22183 /// @brief helper to access iterator member functions in range-based for | |
22184 /// @sa https://json.nlohmann.me/api/basic_json/items/ | |
22185 iteration_proxy<iterator> items() noexcept | |
22186 { | |
22187 return iteration_proxy<iterator>(*this); | |
22188 } | |
22189 | |
22190 /// @brief helper to access iterator member functions in range-based for | |
22191 /// @sa https://json.nlohmann.me/api/basic_json/items/ | |
22192 iteration_proxy<const_iterator> items() const noexcept | |
22193 { | |
22194 return iteration_proxy<const_iterator>(*this); | |
22195 } | |
22196 | |
22197 /// @} | |
22198 | |
22199 ////////////// | |
22200 // capacity // | |
22201 ////////////// | |
22202 | |
22203 /// @name capacity | |
22204 /// @{ | |
22205 | |
22206 /// @brief checks whether the container is empty. | |
22207 /// @sa https://json.nlohmann.me/api/basic_json/empty/ | |
22208 bool empty() const noexcept | |
22209 { | |
22210 switch (m_data.m_type) | |
22211 { | |
22212 case value_t::null: | |
22213 { | |
22214 // null values are empty | |
22215 return true; | |
22216 } | |
22217 | |
22218 case value_t::array: | |
22219 { | |
22220 // delegate call to array_t::empty() | |
22221 return m_data.m_value.array->empty(); | |
22222 } | |
22223 | |
22224 case value_t::object: | |
22225 { | |
22226 // delegate call to object_t::empty() | |
22227 return m_data.m_value.object->empty(); | |
22228 } | |
22229 | |
22230 case value_t::string: | |
22231 case value_t::boolean: | |
22232 case value_t::number_integer: | |
22233 case value_t::number_unsigned: | |
22234 case value_t::number_float: | |
22235 case value_t::binary: | |
22236 case value_t::discarded: | |
22237 default: | |
22238 { | |
22239 // all other types are nonempty | |
22240 return false; | |
22241 } | |
22242 } | |
22243 } | |
22244 | |
22245 /// @brief returns the number of elements | |
22246 /// @sa https://json.nlohmann.me/api/basic_json/size/ | |
22247 size_type size() const noexcept | |
22248 { | |
22249 switch (m_data.m_type) | |
22250 { | |
22251 case value_t::null: | |
22252 { | |
22253 // null values are empty | |
22254 return 0; | |
22255 } | |
22256 | |
22257 case value_t::array: | |
22258 { | |
22259 // delegate call to array_t::size() | |
22260 return m_data.m_value.array->size(); | |
22261 } | |
22262 | |
22263 case value_t::object: | |
22264 { | |
22265 // delegate call to object_t::size() | |
22266 return m_data.m_value.object->size(); | |
22267 } | |
22268 | |
22269 case value_t::string: | |
22270 case value_t::boolean: | |
22271 case value_t::number_integer: | |
22272 case value_t::number_unsigned: | |
22273 case value_t::number_float: | |
22274 case value_t::binary: | |
22275 case value_t::discarded: | |
22276 default: | |
22277 { | |
22278 // all other types have size 1 | |
22279 return 1; | |
22280 } | |
22281 } | |
22282 } | |
22283 | |
22284 /// @brief returns the maximum possible number of elements | |
22285 /// @sa https://json.nlohmann.me/api/basic_json/max_size/ | |
22286 size_type max_size() const noexcept | |
22287 { | |
22288 switch (m_data.m_type) | |
22289 { | |
22290 case value_t::array: | |
22291 { | |
22292 // delegate call to array_t::max_size() | |
22293 return m_data.m_value.array->max_size(); | |
22294 } | |
22295 | |
22296 case value_t::object: | |
22297 { | |
22298 // delegate call to object_t::max_size() | |
22299 return m_data.m_value.object->max_size(); | |
22300 } | |
22301 | |
22302 case value_t::null: | |
22303 case value_t::string: | |
22304 case value_t::boolean: | |
22305 case value_t::number_integer: | |
22306 case value_t::number_unsigned: | |
22307 case value_t::number_float: | |
22308 case value_t::binary: | |
22309 case value_t::discarded: | |
22310 default: | |
22311 { | |
22312 // all other types have max_size() == size() | |
22313 return size(); | |
22314 } | |
22315 } | |
22316 } | |
22317 | |
22318 /// @} | |
22319 | |
22320 /////////////// | |
22321 // modifiers // | |
22322 /////////////// | |
22323 | |
22324 /// @name modifiers | |
22325 /// @{ | |
22326 | |
22327 /// @brief clears the contents | |
22328 /// @sa https://json.nlohmann.me/api/basic_json/clear/ | |
22329 void clear() noexcept | |
22330 { | |
22331 switch (m_data.m_type) | |
22332 { | |
22333 case value_t::number_integer: | |
22334 { | |
22335 m_data.m_value.number_integer = 0; | |
22336 break; | |
22337 } | |
22338 | |
22339 case value_t::number_unsigned: | |
22340 { | |
22341 m_data.m_value.number_unsigned = 0; | |
22342 break; | |
22343 } | |
22344 | |
22345 case value_t::number_float: | |
22346 { | |
22347 m_data.m_value.number_float = 0.0; | |
22348 break; | |
22349 } | |
22350 | |
22351 case value_t::boolean: | |
22352 { | |
22353 m_data.m_value.boolean = false; | |
22354 break; | |
22355 } | |
22356 | |
22357 case value_t::string: | |
22358 { | |
22359 m_data.m_value.string->clear(); | |
22360 break; | |
22361 } | |
22362 | |
22363 case value_t::binary: | |
22364 { | |
22365 m_data.m_value.binary->clear(); | |
22366 break; | |
22367 } | |
22368 | |
22369 case value_t::array: | |
22370 { | |
22371 m_data.m_value.array->clear(); | |
22372 break; | |
22373 } | |
22374 | |
22375 case value_t::object: | |
22376 { | |
22377 m_data.m_value.object->clear(); | |
22378 break; | |
22379 } | |
22380 | |
22381 case value_t::null: | |
22382 case value_t::discarded: | |
22383 default: | |
22384 break; | |
22385 } | |
22386 } | |
22387 | |
22388 /// @brief add an object to an array | |
22389 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ | |
22390 void push_back(basic_json&& val) | |
22391 { | |
22392 // push_back only works for null objects or arrays | |
22393 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) | |
22394 { | |
22395 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); | |
22396 } | |
22397 | |
22398 // transform null object into an array | |
22399 if (is_null()) | |
22400 { | |
22401 m_data.m_type = value_t::array; | |
22402 m_data.m_value = value_t::array; | |
22403 assert_invariant(); | |
22404 } | |
22405 | |
22406 // add element to array (move semantics) | |
22407 const auto old_capacity = m_data.m_value.array->capacity(); | |
22408 m_data.m_value.array->push_back(std::move(val)); | |
22409 set_parent(m_data.m_value.array->back(), old_capacity); | |
22410 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor | |
22411 } | |
22412 | |
22413 /// @brief add an object to an array | |
22414 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ | |
22415 reference operator+=(basic_json&& val) | |
22416 { | |
22417 push_back(std::move(val)); | |
22418 return *this; | |
22419 } | |
22420 | |
22421 /// @brief add an object to an array | |
22422 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ | |
22423 void push_back(const basic_json& val) | |
22424 { | |
22425 // push_back only works for null objects or arrays | |
22426 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) | |
22427 { | |
22428 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); | |
22429 } | |
22430 | |
22431 // transform null object into an array | |
22432 if (is_null()) | |
22433 { | |
22434 m_data.m_type = value_t::array; | |
22435 m_data.m_value = value_t::array; | |
22436 assert_invariant(); | |
22437 } | |
22438 | |
22439 // add element to array | |
22440 const auto old_capacity = m_data.m_value.array->capacity(); | |
22441 m_data.m_value.array->push_back(val); | |
22442 set_parent(m_data.m_value.array->back(), old_capacity); | |
22443 } | |
22444 | |
22445 /// @brief add an object to an array | |
22446 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ | |
22447 reference operator+=(const basic_json& val) | |
22448 { | |
22449 push_back(val); | |
22450 return *this; | |
22451 } | |
22452 | |
22453 /// @brief add an object to an object | |
22454 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ | |
22455 void push_back(const typename object_t::value_type& val) | |
22456 { | |
22457 // push_back only works for null objects or objects | |
22458 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) | |
22459 { | |
22460 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); | |
22461 } | |
22462 | |
22463 // transform null object into an object | |
22464 if (is_null()) | |
22465 { | |
22466 m_data.m_type = value_t::object; | |
22467 m_data.m_value = value_t::object; | |
22468 assert_invariant(); | |
22469 } | |
22470 | |
22471 // add element to object | |
22472 auto res = m_data.m_value.object->insert(val); | |
22473 set_parent(res.first->second); | |
22474 } | |
22475 | |
22476 /// @brief add an object to an object | |
22477 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ | |
22478 reference operator+=(const typename object_t::value_type& val) | |
22479 { | |
22480 push_back(val); | |
22481 return *this; | |
22482 } | |
22483 | |
22484 /// @brief add an object to an object | |
22485 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ | |
22486 void push_back(initializer_list_t init) | |
22487 { | |
22488 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) | |
22489 { | |
22490 basic_json&& key = init.begin()->moved_or_copied(); | |
22491 push_back(typename object_t::value_type( | |
22492 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); | |
22493 } | |
22494 else | |
22495 { | |
22496 push_back(basic_json(init)); | |
22497 } | |
22498 } | |
22499 | |
22500 /// @brief add an object to an object | |
22501 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ | |
22502 reference operator+=(initializer_list_t init) | |
22503 { | |
22504 push_back(init); | |
22505 return *this; | |
22506 } | |
22507 | |
22508 /// @brief add an object to an array | |
22509 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ | |
22510 template<class... Args> | |
22511 reference emplace_back(Args&& ... args) | |
22512 { | |
22513 // emplace_back only works for null objects or arrays | |
22514 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) | |
22515 { | |
22516 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this)); | |
22517 } | |
22518 | |
22519 // transform null object into an array | |
22520 if (is_null()) | |
22521 { | |
22522 m_data.m_type = value_t::array; | |
22523 m_data.m_value = value_t::array; | |
22524 assert_invariant(); | |
22525 } | |
22526 | |
22527 // add element to array (perfect forwarding) | |
22528 const auto old_capacity = m_data.m_value.array->capacity(); | |
22529 m_data.m_value.array->emplace_back(std::forward<Args>(args)...); | |
22530 return set_parent(m_data.m_value.array->back(), old_capacity); | |
22531 } | |
22532 | |
22533 /// @brief add an object to an object if key does not exist | |
22534 /// @sa https://json.nlohmann.me/api/basic_json/emplace/ | |
22535 template<class... Args> | |
22536 std::pair<iterator, bool> emplace(Args&& ... args) | |
22537 { | |
22538 // emplace only works for null objects or arrays | |
22539 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) | |
22540 { | |
22541 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this)); | |
22542 } | |
22543 | |
22544 // transform null object into an object | |
22545 if (is_null()) | |
22546 { | |
22547 m_data.m_type = value_t::object; | |
22548 m_data.m_value = value_t::object; | |
22549 assert_invariant(); | |
22550 } | |
22551 | |
22552 // add element to array (perfect forwarding) | |
22553 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...); | |
22554 set_parent(res.first->second); | |
22555 | |
22556 // create result iterator and set iterator to the result of emplace | |
22557 auto it = begin(); | |
22558 it.m_it.object_iterator = res.first; | |
22559 | |
22560 // return pair of iterator and boolean | |
22561 return {it, res.second}; | |
22562 } | |
22563 | |
22564 /// Helper for insertion of an iterator | |
22565 /// @note: This uses std::distance to support GCC 4.8, | |
22566 /// see https://github.com/nlohmann/json/pull/1257 | |
22567 template<typename... Args> | |
22568 iterator insert_iterator(const_iterator pos, Args&& ... args) | |
22569 { | |
22570 iterator result(this); | |
22571 JSON_ASSERT(m_data.m_value.array != nullptr); | |
22572 | |
22573 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); | |
22574 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); | |
22575 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; | |
22576 | |
22577 // This could have been written as: | |
22578 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); | |
22579 // but the return value of insert is missing in GCC 4.8, so it is written this way instead. | |
22580 | |
22581 set_parents(); | |
22582 return result; | |
22583 } | |
22584 | |
22585 /// @brief inserts element into array | |
22586 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22587 iterator insert(const_iterator pos, const basic_json& val) | |
22588 { | |
22589 // insert only works for arrays | |
22590 if (JSON_HEDLEY_LIKELY(is_array())) | |
22591 { | |
22592 // check if iterator pos fits to this JSON value | |
22593 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) | |
22594 { | |
22595 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); | |
22596 } | |
22597 | |
22598 // insert to array and return iterator | |
22599 return insert_iterator(pos, val); | |
22600 } | |
22601 | |
22602 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); | |
22603 } | |
22604 | |
22605 /// @brief inserts element into array | |
22606 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22607 iterator insert(const_iterator pos, basic_json&& val) | |
22608 { | |
22609 return insert(pos, val); | |
22610 } | |
22611 | |
22612 /// @brief inserts copies of element into array | |
22613 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22614 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) | |
22615 { | |
22616 // insert only works for arrays | |
22617 if (JSON_HEDLEY_LIKELY(is_array())) | |
22618 { | |
22619 // check if iterator pos fits to this JSON value | |
22620 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) | |
22621 { | |
22622 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); | |
22623 } | |
22624 | |
22625 // insert to array and return iterator | |
22626 return insert_iterator(pos, cnt, val); | |
22627 } | |
22628 | |
22629 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); | |
22630 } | |
22631 | |
22632 /// @brief inserts range of elements into array | |
22633 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22634 iterator insert(const_iterator pos, const_iterator first, const_iterator last) | |
22635 { | |
22636 // insert only works for arrays | |
22637 if (JSON_HEDLEY_UNLIKELY(!is_array())) | |
22638 { | |
22639 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); | |
22640 } | |
22641 | |
22642 // check if iterator pos fits to this JSON value | |
22643 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) | |
22644 { | |
22645 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); | |
22646 } | |
22647 | |
22648 // check if range iterators belong to the same JSON object | |
22649 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) | |
22650 { | |
22651 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); | |
22652 } | |
22653 | |
22654 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) | |
22655 { | |
22656 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); | |
22657 } | |
22658 | |
22659 // insert to array and return iterator | |
22660 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); | |
22661 } | |
22662 | |
22663 /// @brief inserts elements from initializer list into array | |
22664 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22665 iterator insert(const_iterator pos, initializer_list_t ilist) | |
22666 { | |
22667 // insert only works for arrays | |
22668 if (JSON_HEDLEY_UNLIKELY(!is_array())) | |
22669 { | |
22670 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); | |
22671 } | |
22672 | |
22673 // check if iterator pos fits to this JSON value | |
22674 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) | |
22675 { | |
22676 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); | |
22677 } | |
22678 | |
22679 // insert to array and return iterator | |
22680 return insert_iterator(pos, ilist.begin(), ilist.end()); | |
22681 } | |
22682 | |
22683 /// @brief inserts range of elements into object | |
22684 /// @sa https://json.nlohmann.me/api/basic_json/insert/ | |
22685 void insert(const_iterator first, const_iterator last) | |
22686 { | |
22687 // insert only works for objects | |
22688 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
22689 { | |
22690 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); | |
22691 } | |
22692 | |
22693 // check if range iterators belong to the same JSON object | |
22694 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) | |
22695 { | |
22696 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); | |
22697 } | |
22698 | |
22699 // passed iterators must belong to objects | |
22700 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) | |
22701 { | |
22702 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); | |
22703 } | |
22704 | |
22705 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); | |
22706 } | |
22707 | |
22708 /// @brief updates a JSON object from another object, overwriting existing keys | |
22709 /// @sa https://json.nlohmann.me/api/basic_json/update/ | |
22710 void update(const_reference j, bool merge_objects = false) | |
22711 { | |
22712 update(j.begin(), j.end(), merge_objects); | |
22713 } | |
22714 | |
22715 /// @brief updates a JSON object from another object, overwriting existing keys | |
22716 /// @sa https://json.nlohmann.me/api/basic_json/update/ | |
22717 void update(const_iterator first, const_iterator last, bool merge_objects = false) | |
22718 { | |
22719 // implicitly convert null value to an empty object | |
22720 if (is_null()) | |
22721 { | |
22722 m_data.m_type = value_t::object; | |
22723 m_data.m_value.object = create<object_t>(); | |
22724 assert_invariant(); | |
22725 } | |
22726 | |
22727 if (JSON_HEDLEY_UNLIKELY(!is_object())) | |
22728 { | |
22729 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this)); | |
22730 } | |
22731 | |
22732 // check if range iterators belong to the same JSON object | |
22733 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) | |
22734 { | |
22735 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); | |
22736 } | |
22737 | |
22738 // passed iterators must belong to objects | |
22739 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) | |
22740 { | |
22741 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object)); | |
22742 } | |
22743 | |
22744 for (auto it = first; it != last; ++it) | |
22745 { | |
22746 if (merge_objects && it.value().is_object()) | |
22747 { | |
22748 auto it2 = m_data.m_value.object->find(it.key()); | |
22749 if (it2 != m_data.m_value.object->end()) | |
22750 { | |
22751 it2->second.update(it.value(), true); | |
22752 continue; | |
22753 } | |
22754 } | |
22755 m_data.m_value.object->operator[](it.key()) = it.value(); | |
22756 #if JSON_DIAGNOSTICS | |
22757 m_data.m_value.object->operator[](it.key()).m_parent = this; | |
22758 #endif | |
22759 } | |
22760 } | |
22761 | |
22762 /// @brief exchanges the values | |
22763 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22764 void swap(reference other) noexcept ( | |
22765 std::is_nothrow_move_constructible<value_t>::value&& | |
22766 std::is_nothrow_move_assignable<value_t>::value&& | |
22767 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22768 std::is_nothrow_move_assignable<json_value>::value | |
22769 ) | |
22770 { | |
22771 std::swap(m_data.m_type, other.m_data.m_type); | |
22772 std::swap(m_data.m_value, other.m_data.m_value); | |
22773 | |
22774 set_parents(); | |
22775 other.set_parents(); | |
22776 assert_invariant(); | |
22777 } | |
22778 | |
22779 /// @brief exchanges the values | |
22780 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22781 friend void swap(reference left, reference right) noexcept ( | |
22782 std::is_nothrow_move_constructible<value_t>::value&& | |
22783 std::is_nothrow_move_assignable<value_t>::value&& | |
22784 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22785 std::is_nothrow_move_assignable<json_value>::value | |
22786 ) | |
22787 { | |
22788 left.swap(right); | |
22789 } | |
22790 | |
22791 /// @brief exchanges the values | |
22792 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22793 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22794 { | |
22795 // swap only works for arrays | |
22796 if (JSON_HEDLEY_LIKELY(is_array())) | |
22797 { | |
22798 using std::swap; | |
22799 swap(*(m_data.m_value.array), other); | |
22800 } | |
22801 else | |
22802 { | |
22803 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); | |
22804 } | |
22805 } | |
22806 | |
22807 /// @brief exchanges the values | |
22808 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22809 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22810 { | |
22811 // swap only works for objects | |
22812 if (JSON_HEDLEY_LIKELY(is_object())) | |
22813 { | |
22814 using std::swap; | |
22815 swap(*(m_data.m_value.object), other); | |
22816 } | |
22817 else | |
22818 { | |
22819 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); | |
22820 } | |
22821 } | |
22822 | |
22823 /// @brief exchanges the values | |
22824 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22825 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22826 { | |
22827 // swap only works for strings | |
22828 if (JSON_HEDLEY_LIKELY(is_string())) | |
22829 { | |
22830 using std::swap; | |
22831 swap(*(m_data.m_value.string), other); | |
22832 } | |
22833 else | |
22834 { | |
22835 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); | |
22836 } | |
22837 } | |
22838 | |
22839 /// @brief exchanges the values | |
22840 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22841 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
22842 { | |
22843 // swap only works for strings | |
22844 if (JSON_HEDLEY_LIKELY(is_binary())) | |
22845 { | |
22846 using std::swap; | |
22847 swap(*(m_data.m_value.binary), other); | |
22848 } | |
22849 else | |
22850 { | |
22851 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); | |
22852 } | |
22853 } | |
22854 | |
22855 /// @brief exchanges the values | |
22856 /// @sa https://json.nlohmann.me/api/basic_json/swap/ | |
22857 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) | |
22858 { | |
22859 // swap only works for strings | |
22860 if (JSON_HEDLEY_LIKELY(is_binary())) | |
22861 { | |
22862 using std::swap; | |
22863 swap(*(m_data.m_value.binary), other); | |
22864 } | |
22865 else | |
22866 { | |
22867 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); | |
22868 } | |
22869 } | |
22870 | |
22871 /// @} | |
22872 | |
22873 ////////////////////////////////////////// | |
22874 // lexicographical comparison operators // | |
22875 ////////////////////////////////////////// | |
22876 | |
22877 /// @name lexicographical comparison operators | |
22878 /// @{ | |
22879 | |
22880 // note parentheses around operands are necessary; see | |
22881 // https://github.com/nlohmann/json/issues/1530 | |
22882 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \ | |
22883 const auto lhs_type = lhs.type(); \ | |
22884 const auto rhs_type = rhs.type(); \ | |
22885 \ | |
22886 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ | |
22887 { \ | |
22888 switch (lhs_type) \ | |
22889 { \ | |
22890 case value_t::array: \ | |
22891 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ | |
22892 \ | |
22893 case value_t::object: \ | |
22894 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ | |
22895 \ | |
22896 case value_t::null: \ | |
22897 return (null_result); \ | |
22898 \ | |
22899 case value_t::string: \ | |
22900 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ | |
22901 \ | |
22902 case value_t::boolean: \ | |
22903 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ | |
22904 \ | |
22905 case value_t::number_integer: \ | |
22906 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ | |
22907 \ | |
22908 case value_t::number_unsigned: \ | |
22909 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ | |
22910 \ | |
22911 case value_t::number_float: \ | |
22912 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ | |
22913 \ | |
22914 case value_t::binary: \ | |
22915 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ | |
22916 \ | |
22917 case value_t::discarded: \ | |
22918 default: \ | |
22919 return (unordered_result); \ | |
22920 } \ | |
22921 } \ | |
22922 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ | |
22923 { \ | |
22924 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ | |
22925 } \ | |
22926 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ | |
22927 { \ | |
22928 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \ | |
22929 } \ | |
22930 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ | |
22931 { \ | |
22932 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ | |
22933 } \ | |
22934 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ | |
22935 { \ | |
22936 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \ | |
22937 } \ | |
22938 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ | |
22939 { \ | |
22940 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ | |
22941 } \ | |
22942 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ | |
22943 { \ | |
22944 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \ | |
22945 } \ | |
22946 else if(compares_unordered(lhs, rhs))\ | |
22947 {\ | |
22948 return (unordered_result);\ | |
22949 }\ | |
22950 \ | |
22951 return (default_result); | |
22952 | |
22953 JSON_PRIVATE_UNLESS_TESTED: | |
22954 // returns true if: | |
22955 // - any operand is NaN and the other operand is of number type | |
22956 // - any operand is discarded | |
22957 // in legacy mode, discarded values are considered ordered if | |
22958 // an operation is computed as an odd number of inverses of others | |
22959 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept | |
22960 { | |
22961 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) | |
22962 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) | |
22963 { | |
22964 return true; | |
22965 } | |
22966 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | |
22967 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse; | |
22968 #else | |
22969 static_cast<void>(inverse); | |
22970 return lhs.is_discarded() || rhs.is_discarded(); | |
22971 #endif | |
22972 } | |
22973 | |
22974 private: | |
22975 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept | |
22976 { | |
22977 return compares_unordered(*this, rhs, inverse); | |
22978 } | |
22979 | |
22980 public: | |
22981 #if JSON_HAS_THREE_WAY_COMPARISON | |
22982 /// @brief comparison: equal | |
22983 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ | |
22984 bool operator==(const_reference rhs) const noexcept | |
22985 { | |
22986 #ifdef __GNUC__ | |
22987 #pragma GCC diagnostic push | |
22988 #pragma GCC diagnostic ignored "-Wfloat-equal" | |
22989 #endif | |
22990 const_reference lhs = *this; | |
22991 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) | |
22992 #ifdef __GNUC__ | |
22993 #pragma GCC diagnostic pop | |
22994 #endif | |
22995 } | |
22996 | |
22997 /// @brief comparison: equal | |
22998 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ | |
22999 template<typename ScalarType> | |
23000 requires std::is_scalar_v<ScalarType> | |
23001 bool operator==(ScalarType rhs) const noexcept | |
23002 { | |
23003 return *this == basic_json(rhs); | |
23004 } | |
23005 | |
23006 /// @brief comparison: not equal | |
23007 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ | |
23008 bool operator!=(const_reference rhs) const noexcept | |
23009 { | |
23010 if (compares_unordered(rhs, true)) | |
23011 { | |
23012 return false; | |
23013 } | |
23014 return !operator==(rhs); | |
23015 } | |
23016 | |
23017 /// @brief comparison: 3-way | |
23018 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ | |
23019 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD* | |
23020 { | |
23021 const_reference lhs = *this; | |
23022 // default_result is used if we cannot compare values. In that case, | |
23023 // we compare types. | |
23024 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD* | |
23025 std::partial_ordering::equivalent, | |
23026 std::partial_ordering::unordered, | |
23027 lhs_type <=> rhs_type) // *NOPAD* | |
23028 } | |
23029 | |
23030 /// @brief comparison: 3-way | |
23031 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ | |
23032 template<typename ScalarType> | |
23033 requires std::is_scalar_v<ScalarType> | |
23034 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD* | |
23035 { | |
23036 return *this <=> basic_json(rhs); // *NOPAD* | |
23037 } | |
23038 | |
23039 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | |
23040 // all operators that are computed as an odd number of inverses of others | |
23041 // need to be overloaded to emulate the legacy comparison behavior | |
23042 | |
23043 /// @brief comparison: less than or equal | |
23044 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ | |
23045 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) | |
23046 bool operator<=(const_reference rhs) const noexcept | |
23047 { | |
23048 if (compares_unordered(rhs, true)) | |
23049 { | |
23050 return false; | |
23051 } | |
23052 return !(rhs < *this); | |
23053 } | |
23054 | |
23055 /// @brief comparison: less than or equal | |
23056 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ | |
23057 template<typename ScalarType> | |
23058 requires std::is_scalar_v<ScalarType> | |
23059 bool operator<=(ScalarType rhs) const noexcept | |
23060 { | |
23061 return *this <= basic_json(rhs); | |
23062 } | |
23063 | |
23064 /// @brief comparison: greater than or equal | |
23065 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ | |
23066 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) | |
23067 bool operator>=(const_reference rhs) const noexcept | |
23068 { | |
23069 if (compares_unordered(rhs, true)) | |
23070 { | |
23071 return false; | |
23072 } | |
23073 return !(*this < rhs); | |
23074 } | |
23075 | |
23076 /// @brief comparison: greater than or equal | |
23077 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ | |
23078 template<typename ScalarType> | |
23079 requires std::is_scalar_v<ScalarType> | |
23080 bool operator>=(ScalarType rhs) const noexcept | |
23081 { | |
23082 return *this >= basic_json(rhs); | |
23083 } | |
23084 #endif | |
23085 #else | |
23086 /// @brief comparison: equal | |
23087 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ | |
23088 friend bool operator==(const_reference lhs, const_reference rhs) noexcept | |
23089 { | |
23090 #ifdef __GNUC__ | |
23091 #pragma GCC diagnostic push | |
23092 #pragma GCC diagnostic ignored "-Wfloat-equal" | |
23093 #endif | |
23094 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) | |
23095 #ifdef __GNUC__ | |
23096 #pragma GCC diagnostic pop | |
23097 #endif | |
23098 } | |
23099 | |
23100 /// @brief comparison: equal | |
23101 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ | |
23102 template<typename ScalarType, typename std::enable_if< | |
23103 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23104 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept | |
23105 { | |
23106 return lhs == basic_json(rhs); | |
23107 } | |
23108 | |
23109 /// @brief comparison: equal | |
23110 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ | |
23111 template<typename ScalarType, typename std::enable_if< | |
23112 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23113 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept | |
23114 { | |
23115 return basic_json(lhs) == rhs; | |
23116 } | |
23117 | |
23118 /// @brief comparison: not equal | |
23119 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ | |
23120 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept | |
23121 { | |
23122 if (compares_unordered(lhs, rhs, true)) | |
23123 { | |
23124 return false; | |
23125 } | |
23126 return !(lhs == rhs); | |
23127 } | |
23128 | |
23129 /// @brief comparison: not equal | |
23130 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ | |
23131 template<typename ScalarType, typename std::enable_if< | |
23132 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23133 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept | |
23134 { | |
23135 return lhs != basic_json(rhs); | |
23136 } | |
23137 | |
23138 /// @brief comparison: not equal | |
23139 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ | |
23140 template<typename ScalarType, typename std::enable_if< | |
23141 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23142 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept | |
23143 { | |
23144 return basic_json(lhs) != rhs; | |
23145 } | |
23146 | |
23147 /// @brief comparison: less than | |
23148 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ | |
23149 friend bool operator<(const_reference lhs, const_reference rhs) noexcept | |
23150 { | |
23151 // default_result is used if we cannot compare values. In that case, | |
23152 // we compare types. Note we have to call the operator explicitly, | |
23153 // because MSVC has problems otherwise. | |
23154 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) | |
23155 } | |
23156 | |
23157 /// @brief comparison: less than | |
23158 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ | |
23159 template<typename ScalarType, typename std::enable_if< | |
23160 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23161 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept | |
23162 { | |
23163 return lhs < basic_json(rhs); | |
23164 } | |
23165 | |
23166 /// @brief comparison: less than | |
23167 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ | |
23168 template<typename ScalarType, typename std::enable_if< | |
23169 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23170 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept | |
23171 { | |
23172 return basic_json(lhs) < rhs; | |
23173 } | |
23174 | |
23175 /// @brief comparison: less than or equal | |
23176 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ | |
23177 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept | |
23178 { | |
23179 if (compares_unordered(lhs, rhs, true)) | |
23180 { | |
23181 return false; | |
23182 } | |
23183 return !(rhs < lhs); | |
23184 } | |
23185 | |
23186 /// @brief comparison: less than or equal | |
23187 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ | |
23188 template<typename ScalarType, typename std::enable_if< | |
23189 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23190 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept | |
23191 { | |
23192 return lhs <= basic_json(rhs); | |
23193 } | |
23194 | |
23195 /// @brief comparison: less than or equal | |
23196 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ | |
23197 template<typename ScalarType, typename std::enable_if< | |
23198 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23199 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept | |
23200 { | |
23201 return basic_json(lhs) <= rhs; | |
23202 } | |
23203 | |
23204 /// @brief comparison: greater than | |
23205 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ | |
23206 friend bool operator>(const_reference lhs, const_reference rhs) noexcept | |
23207 { | |
23208 // double inverse | |
23209 if (compares_unordered(lhs, rhs)) | |
23210 { | |
23211 return false; | |
23212 } | |
23213 return !(lhs <= rhs); | |
23214 } | |
23215 | |
23216 /// @brief comparison: greater than | |
23217 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ | |
23218 template<typename ScalarType, typename std::enable_if< | |
23219 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23220 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept | |
23221 { | |
23222 return lhs > basic_json(rhs); | |
23223 } | |
23224 | |
23225 /// @brief comparison: greater than | |
23226 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ | |
23227 template<typename ScalarType, typename std::enable_if< | |
23228 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23229 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept | |
23230 { | |
23231 return basic_json(lhs) > rhs; | |
23232 } | |
23233 | |
23234 /// @brief comparison: greater than or equal | |
23235 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ | |
23236 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept | |
23237 { | |
23238 if (compares_unordered(lhs, rhs, true)) | |
23239 { | |
23240 return false; | |
23241 } | |
23242 return !(lhs < rhs); | |
23243 } | |
23244 | |
23245 /// @brief comparison: greater than or equal | |
23246 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ | |
23247 template<typename ScalarType, typename std::enable_if< | |
23248 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23249 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept | |
23250 { | |
23251 return lhs >= basic_json(rhs); | |
23252 } | |
23253 | |
23254 /// @brief comparison: greater than or equal | |
23255 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ | |
23256 template<typename ScalarType, typename std::enable_if< | |
23257 std::is_scalar<ScalarType>::value, int>::type = 0> | |
23258 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept | |
23259 { | |
23260 return basic_json(lhs) >= rhs; | |
23261 } | |
23262 #endif | |
23263 | |
23264 #undef JSON_IMPLEMENT_OPERATOR | |
23265 | |
23266 /// @} | |
23267 | |
23268 /////////////////// | |
23269 // serialization // | |
23270 /////////////////// | |
23271 | |
23272 /// @name serialization | |
23273 /// @{ | |
23274 #ifndef JSON_NO_IO | |
23275 /// @brief serialize to stream | |
23276 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ | |
23277 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) | |
23278 { | |
23279 // read width member and use it as indentation parameter if nonzero | |
23280 const bool pretty_print = o.width() > 0; | |
23281 const auto indentation = pretty_print ? o.width() : 0; | |
23282 | |
23283 // reset width to 0 for subsequent calls to this stream | |
23284 o.width(0); | |
23285 | |
23286 // do the actual serialization | |
23287 serializer s(detail::output_adapter<char>(o), o.fill()); | |
23288 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); | |
23289 return o; | |
23290 } | |
23291 | |
23292 /// @brief serialize to stream | |
23293 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ | |
23294 /// @deprecated This function is deprecated since 3.0.0 and will be removed in | |
23295 /// version 4.0.0 of the library. Please use | |
23296 /// operator<<(std::ostream&, const basic_json&) instead; that is, | |
23297 /// replace calls like `j >> o;` with `o << j;`. | |
23298 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) | |
23299 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) | |
23300 { | |
23301 return o << j; | |
23302 } | |
23303 #endif // JSON_NO_IO | |
23304 /// @} | |
23305 | |
23306 ///////////////////// | |
23307 // deserialization // | |
23308 ///////////////////// | |
23309 | |
23310 /// @name deserialization | |
23311 /// @{ | |
23312 | |
23313 /// @brief deserialize from a compatible input | |
23314 /// @sa https://json.nlohmann.me/api/basic_json/parse/ | |
23315 template<typename InputType> | |
23316 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23317 static basic_json parse(InputType&& i, | |
23318 const parser_callback_t cb = nullptr, | |
23319 const bool allow_exceptions = true, | |
23320 const bool ignore_comments = false) | |
23321 { | |
23322 basic_json result; | |
23323 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result); | |
23324 return result; | |
23325 } | |
23326 | |
23327 /// @brief deserialize from a pair of character iterators | |
23328 /// @sa https://json.nlohmann.me/api/basic_json/parse/ | |
23329 template<typename IteratorType> | |
23330 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23331 static basic_json parse(IteratorType first, | |
23332 IteratorType last, | |
23333 const parser_callback_t cb = nullptr, | |
23334 const bool allow_exceptions = true, | |
23335 const bool ignore_comments = false) | |
23336 { | |
23337 basic_json result; | |
23338 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); | |
23339 return result; | |
23340 } | |
23341 | |
23342 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23343 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) | |
23344 static basic_json parse(detail::span_input_adapter&& i, | |
23345 const parser_callback_t cb = nullptr, | |
23346 const bool allow_exceptions = true, | |
23347 const bool ignore_comments = false) | |
23348 { | |
23349 basic_json result; | |
23350 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); | |
23351 return result; | |
23352 } | |
23353 | |
23354 /// @brief check if the input is valid JSON | |
23355 /// @sa https://json.nlohmann.me/api/basic_json/accept/ | |
23356 template<typename InputType> | |
23357 static bool accept(InputType&& i, | |
23358 const bool ignore_comments = false) | |
23359 { | |
23360 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true); | |
23361 } | |
23362 | |
23363 /// @brief check if the input is valid JSON | |
23364 /// @sa https://json.nlohmann.me/api/basic_json/accept/ | |
23365 template<typename IteratorType> | |
23366 static bool accept(IteratorType first, IteratorType last, | |
23367 const bool ignore_comments = false) | |
23368 { | |
23369 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); | |
23370 } | |
23371 | |
23372 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23373 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) | |
23374 static bool accept(detail::span_input_adapter&& i, | |
23375 const bool ignore_comments = false) | |
23376 { | |
23377 return parser(i.get(), nullptr, false, ignore_comments).accept(true); | |
23378 } | |
23379 | |
23380 /// @brief generate SAX events | |
23381 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ | |
23382 template <typename InputType, typename SAX> | |
23383 JSON_HEDLEY_NON_NULL(2) | |
23384 static bool sax_parse(InputType&& i, SAX* sax, | |
23385 input_format_t format = input_format_t::json, | |
23386 const bool strict = true, | |
23387 const bool ignore_comments = false) | |
23388 { | |
23389 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23390 return format == input_format_t::json | |
23391 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) | |
23392 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); | |
23393 } | |
23394 | |
23395 /// @brief generate SAX events | |
23396 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ | |
23397 template<class IteratorType, class SAX> | |
23398 JSON_HEDLEY_NON_NULL(3) | |
23399 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, | |
23400 input_format_t format = input_format_t::json, | |
23401 const bool strict = true, | |
23402 const bool ignore_comments = false) | |
23403 { | |
23404 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23405 return format == input_format_t::json | |
23406 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) | |
23407 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); | |
23408 } | |
23409 | |
23410 /// @brief generate SAX events | |
23411 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ | |
23412 /// @deprecated This function is deprecated since 3.8.0 and will be removed in | |
23413 /// version 4.0.0 of the library. Please use | |
23414 /// sax_parse(ptr, ptr + len) instead. | |
23415 template <typename SAX> | |
23416 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) | |
23417 JSON_HEDLEY_NON_NULL(2) | |
23418 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, | |
23419 input_format_t format = input_format_t::json, | |
23420 const bool strict = true, | |
23421 const bool ignore_comments = false) | |
23422 { | |
23423 auto ia = i.get(); | |
23424 return format == input_format_t::json | |
23425 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23426 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) | |
23427 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23428 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); | |
23429 } | |
23430 #ifndef JSON_NO_IO | |
23431 /// @brief deserialize from stream | |
23432 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ | |
23433 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in | |
23434 /// version 4.0.0 of the library. Please use | |
23435 /// operator>>(std::istream&, basic_json&) instead; that is, | |
23436 /// replace calls like `j << i;` with `i >> j;`. | |
23437 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) | |
23438 friend std::istream& operator<<(basic_json& j, std::istream& i) | |
23439 { | |
23440 return operator>>(i, j); | |
23441 } | |
23442 | |
23443 /// @brief deserialize from stream | |
23444 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ | |
23445 friend std::istream& operator>>(std::istream& i, basic_json& j) | |
23446 { | |
23447 parser(detail::input_adapter(i)).parse(false, j); | |
23448 return i; | |
23449 } | |
23450 #endif // JSON_NO_IO | |
23451 /// @} | |
23452 | |
23453 /////////////////////////// | |
23454 // convenience functions // | |
23455 /////////////////////////// | |
23456 | |
23457 /// @brief return the type as string | |
23458 /// @sa https://json.nlohmann.me/api/basic_json/type_name/ | |
23459 JSON_HEDLEY_RETURNS_NON_NULL | |
23460 const char* type_name() const noexcept | |
23461 { | |
23462 switch (m_data.m_type) | |
23463 { | |
23464 case value_t::null: | |
23465 return "null"; | |
23466 case value_t::object: | |
23467 return "object"; | |
23468 case value_t::array: | |
23469 return "array"; | |
23470 case value_t::string: | |
23471 return "string"; | |
23472 case value_t::boolean: | |
23473 return "boolean"; | |
23474 case value_t::binary: | |
23475 return "binary"; | |
23476 case value_t::discarded: | |
23477 return "discarded"; | |
23478 case value_t::number_integer: | |
23479 case value_t::number_unsigned: | |
23480 case value_t::number_float: | |
23481 default: | |
23482 return "number"; | |
23483 } | |
23484 } | |
23485 | |
23486 JSON_PRIVATE_UNLESS_TESTED: | |
23487 ////////////////////// | |
23488 // member variables // | |
23489 ////////////////////// | |
23490 | |
23491 struct data | |
23492 { | |
23493 /// the type of the current element | |
23494 value_t m_type = value_t::null; | |
23495 | |
23496 /// the value of the current element | |
23497 json_value m_value = {}; | |
23498 | |
23499 data(const value_t v) | |
23500 : m_type(v), m_value(v) | |
23501 { | |
23502 } | |
23503 | |
23504 data(size_type cnt, const basic_json& val) | |
23505 : m_type(value_t::array) | |
23506 { | |
23507 m_value.array = create<array_t>(cnt, val); | |
23508 } | |
23509 | |
23510 data() noexcept = default; | |
23511 data(data&&) noexcept = default; | |
23512 data(const data&) noexcept = delete; | |
23513 data& operator=(data&&) noexcept = delete; | |
23514 data& operator=(const data&) noexcept = delete; | |
23515 | |
23516 ~data() noexcept | |
23517 { | |
23518 m_value.destroy(m_type); | |
23519 } | |
23520 }; | |
23521 | |
23522 data m_data = {}; | |
23523 | |
23524 #if JSON_DIAGNOSTICS | |
23525 /// a pointer to a parent value (for debugging purposes) | |
23526 basic_json* m_parent = nullptr; | |
23527 #endif | |
23528 | |
23529 ////////////////////////////////////////// | |
23530 // binary serialization/deserialization // | |
23531 ////////////////////////////////////////// | |
23532 | |
23533 /// @name binary serialization/deserialization support | |
23534 /// @{ | |
23535 | |
23536 public: | |
23537 /// @brief create a CBOR serialization of a given JSON value | |
23538 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ | |
23539 static std::vector<std::uint8_t> to_cbor(const basic_json& j) | |
23540 { | |
23541 std::vector<std::uint8_t> result; | |
23542 to_cbor(j, result); | |
23543 return result; | |
23544 } | |
23545 | |
23546 /// @brief create a CBOR serialization of a given JSON value | |
23547 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ | |
23548 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) | |
23549 { | |
23550 binary_writer<std::uint8_t>(o).write_cbor(j); | |
23551 } | |
23552 | |
23553 /// @brief create a CBOR serialization of a given JSON value | |
23554 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ | |
23555 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) | |
23556 { | |
23557 binary_writer<char>(o).write_cbor(j); | |
23558 } | |
23559 | |
23560 /// @brief create a MessagePack serialization of a given JSON value | |
23561 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ | |
23562 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) | |
23563 { | |
23564 std::vector<std::uint8_t> result; | |
23565 to_msgpack(j, result); | |
23566 return result; | |
23567 } | |
23568 | |
23569 /// @brief create a MessagePack serialization of a given JSON value | |
23570 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ | |
23571 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) | |
23572 { | |
23573 binary_writer<std::uint8_t>(o).write_msgpack(j); | |
23574 } | |
23575 | |
23576 /// @brief create a MessagePack serialization of a given JSON value | |
23577 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ | |
23578 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) | |
23579 { | |
23580 binary_writer<char>(o).write_msgpack(j); | |
23581 } | |
23582 | |
23583 /// @brief create a UBJSON serialization of a given JSON value | |
23584 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ | |
23585 static std::vector<std::uint8_t> to_ubjson(const basic_json& j, | |
23586 const bool use_size = false, | |
23587 const bool use_type = false) | |
23588 { | |
23589 std::vector<std::uint8_t> result; | |
23590 to_ubjson(j, result, use_size, use_type); | |
23591 return result; | |
23592 } | |
23593 | |
23594 /// @brief create a UBJSON serialization of a given JSON value | |
23595 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ | |
23596 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o, | |
23597 const bool use_size = false, const bool use_type = false) | |
23598 { | |
23599 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type); | |
23600 } | |
23601 | |
23602 /// @brief create a UBJSON serialization of a given JSON value | |
23603 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ | |
23604 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, | |
23605 const bool use_size = false, const bool use_type = false) | |
23606 { | |
23607 binary_writer<char>(o).write_ubjson(j, use_size, use_type); | |
23608 } | |
23609 | |
23610 /// @brief create a BJData serialization of a given JSON value | |
23611 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ | |
23612 static std::vector<std::uint8_t> to_bjdata(const basic_json& j, | |
23613 const bool use_size = false, | |
23614 const bool use_type = false) | |
23615 { | |
23616 std::vector<std::uint8_t> result; | |
23617 to_bjdata(j, result, use_size, use_type); | |
23618 return result; | |
23619 } | |
23620 | |
23621 /// @brief create a BJData serialization of a given JSON value | |
23622 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ | |
23623 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, | |
23624 const bool use_size = false, const bool use_type = false) | |
23625 { | |
23626 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); | |
23627 } | |
23628 | |
23629 /// @brief create a BJData serialization of a given JSON value | |
23630 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ | |
23631 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, | |
23632 const bool use_size = false, const bool use_type = false) | |
23633 { | |
23634 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); | |
23635 } | |
23636 | |
23637 /// @brief create a BSON serialization of a given JSON value | |
23638 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ | |
23639 static std::vector<std::uint8_t> to_bson(const basic_json& j) | |
23640 { | |
23641 std::vector<std::uint8_t> result; | |
23642 to_bson(j, result); | |
23643 return result; | |
23644 } | |
23645 | |
23646 /// @brief create a BSON serialization of a given JSON value | |
23647 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ | |
23648 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) | |
23649 { | |
23650 binary_writer<std::uint8_t>(o).write_bson(j); | |
23651 } | |
23652 | |
23653 /// @brief create a BSON serialization of a given JSON value | |
23654 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ | |
23655 static void to_bson(const basic_json& j, detail::output_adapter<char> o) | |
23656 { | |
23657 binary_writer<char>(o).write_bson(j); | |
23658 } | |
23659 | |
23660 /// @brief create a JSON value from an input in CBOR format | |
23661 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ | |
23662 template<typename InputType> | |
23663 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23664 static basic_json from_cbor(InputType&& i, | |
23665 const bool strict = true, | |
23666 const bool allow_exceptions = true, | |
23667 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) | |
23668 { | |
23669 basic_json result; | |
23670 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23671 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23672 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); | |
23673 return res ? result : basic_json(value_t::discarded); | |
23674 } | |
23675 | |
23676 /// @brief create a JSON value from an input in CBOR format | |
23677 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ | |
23678 template<typename IteratorType> | |
23679 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23680 static basic_json from_cbor(IteratorType first, IteratorType last, | |
23681 const bool strict = true, | |
23682 const bool allow_exceptions = true, | |
23683 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) | |
23684 { | |
23685 basic_json result; | |
23686 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23687 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23688 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); | |
23689 return res ? result : basic_json(value_t::discarded); | |
23690 } | |
23691 | |
23692 template<typename T> | |
23693 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23694 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) | |
23695 static basic_json from_cbor(const T* ptr, std::size_t len, | |
23696 const bool strict = true, | |
23697 const bool allow_exceptions = true, | |
23698 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) | |
23699 { | |
23700 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); | |
23701 } | |
23702 | |
23703 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23704 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) | |
23705 static basic_json from_cbor(detail::span_input_adapter&& i, | |
23706 const bool strict = true, | |
23707 const bool allow_exceptions = true, | |
23708 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) | |
23709 { | |
23710 basic_json result; | |
23711 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23712 auto ia = i.get(); | |
23713 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23714 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); | |
23715 return res ? result : basic_json(value_t::discarded); | |
23716 } | |
23717 | |
23718 /// @brief create a JSON value from an input in MessagePack format | |
23719 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ | |
23720 template<typename InputType> | |
23721 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23722 static basic_json from_msgpack(InputType&& i, | |
23723 const bool strict = true, | |
23724 const bool allow_exceptions = true) | |
23725 { | |
23726 basic_json result; | |
23727 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23728 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23729 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); | |
23730 return res ? result : basic_json(value_t::discarded); | |
23731 } | |
23732 | |
23733 /// @brief create a JSON value from an input in MessagePack format | |
23734 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ | |
23735 template<typename IteratorType> | |
23736 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23737 static basic_json from_msgpack(IteratorType first, IteratorType last, | |
23738 const bool strict = true, | |
23739 const bool allow_exceptions = true) | |
23740 { | |
23741 basic_json result; | |
23742 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23743 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23744 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); | |
23745 return res ? result : basic_json(value_t::discarded); | |
23746 } | |
23747 | |
23748 template<typename T> | |
23749 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23750 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) | |
23751 static basic_json from_msgpack(const T* ptr, std::size_t len, | |
23752 const bool strict = true, | |
23753 const bool allow_exceptions = true) | |
23754 { | |
23755 return from_msgpack(ptr, ptr + len, strict, allow_exceptions); | |
23756 } | |
23757 | |
23758 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23759 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) | |
23760 static basic_json from_msgpack(detail::span_input_adapter&& i, | |
23761 const bool strict = true, | |
23762 const bool allow_exceptions = true) | |
23763 { | |
23764 basic_json result; | |
23765 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23766 auto ia = i.get(); | |
23767 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23768 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); | |
23769 return res ? result : basic_json(value_t::discarded); | |
23770 } | |
23771 | |
23772 /// @brief create a JSON value from an input in UBJSON format | |
23773 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ | |
23774 template<typename InputType> | |
23775 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23776 static basic_json from_ubjson(InputType&& i, | |
23777 const bool strict = true, | |
23778 const bool allow_exceptions = true) | |
23779 { | |
23780 basic_json result; | |
23781 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23782 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23783 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); | |
23784 return res ? result : basic_json(value_t::discarded); | |
23785 } | |
23786 | |
23787 /// @brief create a JSON value from an input in UBJSON format | |
23788 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ | |
23789 template<typename IteratorType> | |
23790 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23791 static basic_json from_ubjson(IteratorType first, IteratorType last, | |
23792 const bool strict = true, | |
23793 const bool allow_exceptions = true) | |
23794 { | |
23795 basic_json result; | |
23796 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23797 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23798 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); | |
23799 return res ? result : basic_json(value_t::discarded); | |
23800 } | |
23801 | |
23802 template<typename T> | |
23803 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23804 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) | |
23805 static basic_json from_ubjson(const T* ptr, std::size_t len, | |
23806 const bool strict = true, | |
23807 const bool allow_exceptions = true) | |
23808 { | |
23809 return from_ubjson(ptr, ptr + len, strict, allow_exceptions); | |
23810 } | |
23811 | |
23812 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23813 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) | |
23814 static basic_json from_ubjson(detail::span_input_adapter&& i, | |
23815 const bool strict = true, | |
23816 const bool allow_exceptions = true) | |
23817 { | |
23818 basic_json result; | |
23819 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23820 auto ia = i.get(); | |
23821 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23822 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); | |
23823 return res ? result : basic_json(value_t::discarded); | |
23824 } | |
23825 | |
23826 /// @brief create a JSON value from an input in BJData format | |
23827 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ | |
23828 template<typename InputType> | |
23829 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23830 static basic_json from_bjdata(InputType&& i, | |
23831 const bool strict = true, | |
23832 const bool allow_exceptions = true) | |
23833 { | |
23834 basic_json result; | |
23835 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23836 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23837 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); | |
23838 return res ? result : basic_json(value_t::discarded); | |
23839 } | |
23840 | |
23841 /// @brief create a JSON value from an input in BJData format | |
23842 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ | |
23843 template<typename IteratorType> | |
23844 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23845 static basic_json from_bjdata(IteratorType first, IteratorType last, | |
23846 const bool strict = true, | |
23847 const bool allow_exceptions = true) | |
23848 { | |
23849 basic_json result; | |
23850 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23851 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23852 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); | |
23853 return res ? result : basic_json(value_t::discarded); | |
23854 } | |
23855 | |
23856 /// @brief create a JSON value from an input in BSON format | |
23857 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ | |
23858 template<typename InputType> | |
23859 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23860 static basic_json from_bson(InputType&& i, | |
23861 const bool strict = true, | |
23862 const bool allow_exceptions = true) | |
23863 { | |
23864 basic_json result; | |
23865 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23866 auto ia = detail::input_adapter(std::forward<InputType>(i)); | |
23867 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); | |
23868 return res ? result : basic_json(value_t::discarded); | |
23869 } | |
23870 | |
23871 /// @brief create a JSON value from an input in BSON format | |
23872 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ | |
23873 template<typename IteratorType> | |
23874 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23875 static basic_json from_bson(IteratorType first, IteratorType last, | |
23876 const bool strict = true, | |
23877 const bool allow_exceptions = true) | |
23878 { | |
23879 basic_json result; | |
23880 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23881 auto ia = detail::input_adapter(std::move(first), std::move(last)); | |
23882 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); | |
23883 return res ? result : basic_json(value_t::discarded); | |
23884 } | |
23885 | |
23886 template<typename T> | |
23887 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23888 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) | |
23889 static basic_json from_bson(const T* ptr, std::size_t len, | |
23890 const bool strict = true, | |
23891 const bool allow_exceptions = true) | |
23892 { | |
23893 return from_bson(ptr, ptr + len, strict, allow_exceptions); | |
23894 } | |
23895 | |
23896 JSON_HEDLEY_WARN_UNUSED_RESULT | |
23897 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) | |
23898 static basic_json from_bson(detail::span_input_adapter&& i, | |
23899 const bool strict = true, | |
23900 const bool allow_exceptions = true) | |
23901 { | |
23902 basic_json result; | |
23903 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); | |
23904 auto ia = i.get(); | |
23905 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) | |
23906 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); | |
23907 return res ? result : basic_json(value_t::discarded); | |
23908 } | |
23909 /// @} | |
23910 | |
23911 ////////////////////////// | |
23912 // JSON Pointer support // | |
23913 ////////////////////////// | |
23914 | |
23915 /// @name JSON Pointer functions | |
23916 /// @{ | |
23917 | |
23918 /// @brief access specified element via JSON Pointer | |
23919 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
23920 reference operator[](const json_pointer& ptr) | |
23921 { | |
23922 return ptr.get_unchecked(this); | |
23923 } | |
23924 | |
23925 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> | |
23926 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
23927 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) | |
23928 { | |
23929 return ptr.get_unchecked(this); | |
23930 } | |
23931 | |
23932 /// @brief access specified element via JSON Pointer | |
23933 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ | |
23934 const_reference operator[](const json_pointer& ptr) const | |
23935 { | |
23936 return ptr.get_unchecked(this); | |
23937 } | |
23938 | |
23939 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> | |
23940 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
23941 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const | |
23942 { | |
23943 return ptr.get_unchecked(this); | |
23944 } | |
23945 | |
23946 /// @brief access specified element via JSON Pointer | |
23947 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
23948 reference at(const json_pointer& ptr) | |
23949 { | |
23950 return ptr.get_checked(this); | |
23951 } | |
23952 | |
23953 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> | |
23954 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
23955 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) | |
23956 { | |
23957 return ptr.get_checked(this); | |
23958 } | |
23959 | |
23960 /// @brief access specified element via JSON Pointer | |
23961 /// @sa https://json.nlohmann.me/api/basic_json/at/ | |
23962 const_reference at(const json_pointer& ptr) const | |
23963 { | |
23964 return ptr.get_checked(this); | |
23965 } | |
23966 | |
23967 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> | |
23968 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) | |
23969 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const | |
23970 { | |
23971 return ptr.get_checked(this); | |
23972 } | |
23973 | |
23974 /// @brief return flattened JSON value | |
23975 /// @sa https://json.nlohmann.me/api/basic_json/flatten/ | |
23976 basic_json flatten() const | |
23977 { | |
23978 basic_json result(value_t::object); | |
23979 json_pointer::flatten("", *this, result); | |
23980 return result; | |
23981 } | |
23982 | |
23983 /// @brief unflatten a previously flattened JSON value | |
23984 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ | |
23985 basic_json unflatten() const | |
23986 { | |
23987 return json_pointer::unflatten(*this); | |
23988 } | |
23989 | |
23990 /// @} | |
23991 | |
23992 ////////////////////////// | |
23993 // JSON Patch functions // | |
23994 ////////////////////////// | |
23995 | |
23996 /// @name JSON Patch functions | |
23997 /// @{ | |
23998 | |
23999 /// @brief applies a JSON patch in-place without copying the object | |
24000 /// @sa https://json.nlohmann.me/api/basic_json/patch/ | |
24001 void patch_inplace(const basic_json& json_patch) | |
24002 { | |
24003 basic_json& result = *this; | |
24004 // the valid JSON Patch operations | |
24005 enum class patch_operations {add, remove, replace, move, copy, test, invalid}; | |
24006 | |
24007 const auto get_op = [](const std::string & op) | |
24008 { | |
24009 if (op == "add") | |
24010 { | |
24011 return patch_operations::add; | |
24012 } | |
24013 if (op == "remove") | |
24014 { | |
24015 return patch_operations::remove; | |
24016 } | |
24017 if (op == "replace") | |
24018 { | |
24019 return patch_operations::replace; | |
24020 } | |
24021 if (op == "move") | |
24022 { | |
24023 return patch_operations::move; | |
24024 } | |
24025 if (op == "copy") | |
24026 { | |
24027 return patch_operations::copy; | |
24028 } | |
24029 if (op == "test") | |
24030 { | |
24031 return patch_operations::test; | |
24032 } | |
24033 | |
24034 return patch_operations::invalid; | |
24035 }; | |
24036 | |
24037 // wrapper for "add" operation; add value at ptr | |
24038 const auto operation_add = [&result](json_pointer & ptr, basic_json val) | |
24039 { | |
24040 // adding to the root of the target document means replacing it | |
24041 if (ptr.empty()) | |
24042 { | |
24043 result = val; | |
24044 return; | |
24045 } | |
24046 | |
24047 // make sure the top element of the pointer exists | |
24048 json_pointer const top_pointer = ptr.top(); | |
24049 if (top_pointer != ptr) | |
24050 { | |
24051 result.at(top_pointer); | |
24052 } | |
24053 | |
24054 // get reference to parent of JSON pointer ptr | |
24055 const auto last_path = ptr.back(); | |
24056 ptr.pop_back(); | |
24057 // parent must exist when performing patch add per RFC6902 specs | |
24058 basic_json& parent = result.at(ptr); | |
24059 | |
24060 switch (parent.m_data.m_type) | |
24061 { | |
24062 case value_t::null: | |
24063 case value_t::object: | |
24064 { | |
24065 // use operator[] to add value | |
24066 parent[last_path] = val; | |
24067 break; | |
24068 } | |
24069 | |
24070 case value_t::array: | |
24071 { | |
24072 if (last_path == "-") | |
24073 { | |
24074 // special case: append to back | |
24075 parent.push_back(val); | |
24076 } | |
24077 else | |
24078 { | |
24079 const auto idx = json_pointer::template array_index<basic_json_t>(last_path); | |
24080 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) | |
24081 { | |
24082 // avoid undefined behavior | |
24083 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent)); | |
24084 } | |
24085 | |
24086 // default case: insert add offset | |
24087 parent.insert(parent.begin() + static_cast<difference_type>(idx), val); | |
24088 } | |
24089 break; | |
24090 } | |
24091 | |
24092 // if there exists a parent it cannot be primitive | |
24093 case value_t::string: // LCOV_EXCL_LINE | |
24094 case value_t::boolean: // LCOV_EXCL_LINE | |
24095 case value_t::number_integer: // LCOV_EXCL_LINE | |
24096 case value_t::number_unsigned: // LCOV_EXCL_LINE | |
24097 case value_t::number_float: // LCOV_EXCL_LINE | |
24098 case value_t::binary: // LCOV_EXCL_LINE | |
24099 case value_t::discarded: // LCOV_EXCL_LINE | |
24100 default: // LCOV_EXCL_LINE | |
24101 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE | |
24102 } | |
24103 }; | |
24104 | |
24105 // wrapper for "remove" operation; remove value at ptr | |
24106 const auto operation_remove = [this, & result](json_pointer & ptr) | |
24107 { | |
24108 // get reference to parent of JSON pointer ptr | |
24109 const auto last_path = ptr.back(); | |
24110 ptr.pop_back(); | |
24111 basic_json& parent = result.at(ptr); | |
24112 | |
24113 // remove child | |
24114 if (parent.is_object()) | |
24115 { | |
24116 // perform range check | |
24117 auto it = parent.find(last_path); | |
24118 if (JSON_HEDLEY_LIKELY(it != parent.end())) | |
24119 { | |
24120 parent.erase(it); | |
24121 } | |
24122 else | |
24123 { | |
24124 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this)); | |
24125 } | |
24126 } | |
24127 else if (parent.is_array()) | |
24128 { | |
24129 // note erase performs range check | |
24130 parent.erase(json_pointer::template array_index<basic_json_t>(last_path)); | |
24131 } | |
24132 }; | |
24133 | |
24134 // type check: top level value must be an array | |
24135 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) | |
24136 { | |
24137 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch)); | |
24138 } | |
24139 | |
24140 // iterate and apply the operations | |
24141 for (const auto& val : json_patch) | |
24142 { | |
24143 // wrapper to get a value for an operation | |
24144 const auto get_value = [&val](const std::string & op, | |
24145 const std::string & member, | |
24146 bool string_type) -> basic_json & | |
24147 { | |
24148 // find value | |
24149 auto it = val.m_data.m_value.object->find(member); | |
24150 | |
24151 // context-sensitive error message | |
24152 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); | |
24153 | |
24154 // check if desired value is present | |
24155 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) | |
24156 { | |
24157 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) | |
24158 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); | |
24159 } | |
24160 | |
24161 // check if result is of type string | |
24162 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) | |
24163 { | |
24164 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) | |
24165 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val)); | |
24166 } | |
24167 | |
24168 // no error: return value | |
24169 return it->second; | |
24170 }; | |
24171 | |
24172 // type check: every element of the array must be an object | |
24173 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) | |
24174 { | |
24175 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val)); | |
24176 } | |
24177 | |
24178 // collect mandatory members | |
24179 const auto op = get_value("op", "op", true).template get<std::string>(); | |
24180 const auto path = get_value(op, "path", true).template get<std::string>(); | |
24181 json_pointer ptr(path); | |
24182 | |
24183 switch (get_op(op)) | |
24184 { | |
24185 case patch_operations::add: | |
24186 { | |
24187 operation_add(ptr, get_value("add", "value", false)); | |
24188 break; | |
24189 } | |
24190 | |
24191 case patch_operations::remove: | |
24192 { | |
24193 operation_remove(ptr); | |
24194 break; | |
24195 } | |
24196 | |
24197 case patch_operations::replace: | |
24198 { | |
24199 // the "path" location must exist - use at() | |
24200 result.at(ptr) = get_value("replace", "value", false); | |
24201 break; | |
24202 } | |
24203 | |
24204 case patch_operations::move: | |
24205 { | |
24206 const auto from_path = get_value("move", "from", true).template get<std::string>(); | |
24207 json_pointer from_ptr(from_path); | |
24208 | |
24209 // the "from" location must exist - use at() | |
24210 basic_json const v = result.at(from_ptr); | |
24211 | |
24212 // The move operation is functionally identical to a | |
24213 // "remove" operation on the "from" location, followed | |
24214 // immediately by an "add" operation at the target | |
24215 // location with the value that was just removed. | |
24216 operation_remove(from_ptr); | |
24217 operation_add(ptr, v); | |
24218 break; | |
24219 } | |
24220 | |
24221 case patch_operations::copy: | |
24222 { | |
24223 const auto from_path = get_value("copy", "from", true).template get<std::string>(); | |
24224 const json_pointer from_ptr(from_path); | |
24225 | |
24226 // the "from" location must exist - use at() | |
24227 basic_json const v = result.at(from_ptr); | |
24228 | |
24229 // The copy is functionally identical to an "add" | |
24230 // operation at the target location using the value | |
24231 // specified in the "from" member. | |
24232 operation_add(ptr, v); | |
24233 break; | |
24234 } | |
24235 | |
24236 case patch_operations::test: | |
24237 { | |
24238 bool success = false; | |
24239 JSON_TRY | |
24240 { | |
24241 // check if "value" matches the one at "path" | |
24242 // the "path" location must exist - use at() | |
24243 success = (result.at(ptr) == get_value("test", "value", false)); | |
24244 } | |
24245 JSON_INTERNAL_CATCH (out_of_range&) | |
24246 { | |
24247 // ignore out of range errors: success remains false | |
24248 } | |
24249 | |
24250 // throw an exception if test fails | |
24251 if (JSON_HEDLEY_UNLIKELY(!success)) | |
24252 { | |
24253 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val)); | |
24254 } | |
24255 | |
24256 break; | |
24257 } | |
24258 | |
24259 case patch_operations::invalid: | |
24260 default: | |
24261 { | |
24262 // op must be "add", "remove", "replace", "move", "copy", or | |
24263 // "test" | |
24264 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val)); | |
24265 } | |
24266 } | |
24267 } | |
24268 } | |
24269 | |
24270 /// @brief applies a JSON patch to a copy of the current object | |
24271 /// @sa https://json.nlohmann.me/api/basic_json/patch/ | |
24272 basic_json patch(const basic_json& json_patch) const | |
24273 { | |
24274 basic_json result = *this; | |
24275 result.patch_inplace(json_patch); | |
24276 return result; | |
24277 } | |
24278 | |
24279 /// @brief creates a diff as a JSON patch | |
24280 /// @sa https://json.nlohmann.me/api/basic_json/diff/ | |
24281 JSON_HEDLEY_WARN_UNUSED_RESULT | |
24282 static basic_json diff(const basic_json& source, const basic_json& target, | |
24283 const std::string& path = "") | |
24284 { | |
24285 // the patch | |
24286 basic_json result(value_t::array); | |
24287 | |
24288 // if the values are the same, return empty patch | |
24289 if (source == target) | |
24290 { | |
24291 return result; | |
24292 } | |
24293 | |
24294 if (source.type() != target.type()) | |
24295 { | |
24296 // different types: replace value | |
24297 result.push_back( | |
24298 { | |
24299 {"op", "replace"}, {"path", path}, {"value", target} | |
24300 }); | |
24301 return result; | |
24302 } | |
24303 | |
24304 switch (source.type()) | |
24305 { | |
24306 case value_t::array: | |
24307 { | |
24308 // first pass: traverse common elements | |
24309 std::size_t i = 0; | |
24310 while (i < source.size() && i < target.size()) | |
24311 { | |
24312 // recursive call to compare array values at index i | |
24313 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); | |
24314 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); | |
24315 ++i; | |
24316 } | |
24317 | |
24318 // We now reached the end of at least one array | |
24319 // in a second pass, traverse the remaining elements | |
24320 | |
24321 // remove my remaining elements | |
24322 const auto end_index = static_cast<difference_type>(result.size()); | |
24323 while (i < source.size()) | |
24324 { | |
24325 // add operations in reverse order to avoid invalid | |
24326 // indices | |
24327 result.insert(result.begin() + end_index, object( | |
24328 { | |
24329 {"op", "remove"}, | |
24330 {"path", detail::concat(path, '/', std::to_string(i))} | |
24331 })); | |
24332 ++i; | |
24333 } | |
24334 | |
24335 // add other remaining elements | |
24336 while (i < target.size()) | |
24337 { | |
24338 result.push_back( | |
24339 { | |
24340 {"op", "add"}, | |
24341 {"path", detail::concat(path, "/-")}, | |
24342 {"value", target[i]} | |
24343 }); | |
24344 ++i; | |
24345 } | |
24346 | |
24347 break; | |
24348 } | |
24349 | |
24350 case value_t::object: | |
24351 { | |
24352 // first pass: traverse this object's elements | |
24353 for (auto it = source.cbegin(); it != source.cend(); ++it) | |
24354 { | |
24355 // escape the key name to be used in a JSON patch | |
24356 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); | |
24357 | |
24358 if (target.find(it.key()) != target.end()) | |
24359 { | |
24360 // recursive call to compare object values at key it | |
24361 auto temp_diff = diff(it.value(), target[it.key()], path_key); | |
24362 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); | |
24363 } | |
24364 else | |
24365 { | |
24366 // found a key that is not in o -> remove it | |
24367 result.push_back(object( | |
24368 { | |
24369 {"op", "remove"}, {"path", path_key} | |
24370 })); | |
24371 } | |
24372 } | |
24373 | |
24374 // second pass: traverse other object's elements | |
24375 for (auto it = target.cbegin(); it != target.cend(); ++it) | |
24376 { | |
24377 if (source.find(it.key()) == source.end()) | |
24378 { | |
24379 // found a key that is not in this -> add it | |
24380 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); | |
24381 result.push_back( | |
24382 { | |
24383 {"op", "add"}, {"path", path_key}, | |
24384 {"value", it.value()} | |
24385 }); | |
24386 } | |
24387 } | |
24388 | |
24389 break; | |
24390 } | |
24391 | |
24392 case value_t::null: | |
24393 case value_t::string: | |
24394 case value_t::boolean: | |
24395 case value_t::number_integer: | |
24396 case value_t::number_unsigned: | |
24397 case value_t::number_float: | |
24398 case value_t::binary: | |
24399 case value_t::discarded: | |
24400 default: | |
24401 { | |
24402 // both primitive type: replace value | |
24403 result.push_back( | |
24404 { | |
24405 {"op", "replace"}, {"path", path}, {"value", target} | |
24406 }); | |
24407 break; | |
24408 } | |
24409 } | |
24410 | |
24411 return result; | |
24412 } | |
24413 /// @} | |
24414 | |
24415 //////////////////////////////// | |
24416 // JSON Merge Patch functions // | |
24417 //////////////////////////////// | |
24418 | |
24419 /// @name JSON Merge Patch functions | |
24420 /// @{ | |
24421 | |
24422 /// @brief applies a JSON Merge Patch | |
24423 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ | |
24424 void merge_patch(const basic_json& apply_patch) | |
24425 { | |
24426 if (apply_patch.is_object()) | |
24427 { | |
24428 if (!is_object()) | |
24429 { | |
24430 *this = object(); | |
24431 } | |
24432 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) | |
24433 { | |
24434 if (it.value().is_null()) | |
24435 { | |
24436 erase(it.key()); | |
24437 } | |
24438 else | |
24439 { | |
24440 operator[](it.key()).merge_patch(it.value()); | |
24441 } | |
24442 } | |
24443 } | |
24444 else | |
24445 { | |
24446 *this = apply_patch; | |
24447 } | |
24448 } | |
24449 | |
24450 /// @} | |
24451 }; | |
24452 | |
24453 /// @brief user-defined to_string function for JSON values | |
24454 /// @sa https://json.nlohmann.me/api/basic_json/to_string/ | |
24455 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
24456 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) | |
24457 { | |
24458 return j.dump(); | |
24459 } | |
24460 | |
24461 inline namespace literals | |
24462 { | |
24463 inline namespace json_literals | |
24464 { | |
24465 | |
24466 /// @brief user-defined string literal for JSON values | |
24467 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ | |
24468 JSON_HEDLEY_NON_NULL(1) | |
24469 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) | |
24470 inline nlohmann::json operator ""_json(const char* s, std::size_t n) | |
24471 #else | |
24472 inline nlohmann::json operator "" _json(const char* s, std::size_t n) | |
24473 #endif | |
24474 { | |
24475 return nlohmann::json::parse(s, s + n); | |
24476 } | |
24477 | |
24478 /// @brief user-defined string literal for JSON pointer | |
24479 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ | |
24480 JSON_HEDLEY_NON_NULL(1) | |
24481 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) | |
24482 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) | |
24483 #else | |
24484 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) | |
24485 #endif | |
24486 { | |
24487 return nlohmann::json::json_pointer(std::string(s, n)); | |
24488 } | |
24489 | |
24490 } // namespace json_literals | |
24491 } // namespace literals | |
24492 NLOHMANN_JSON_NAMESPACE_END | |
24493 | |
24494 /////////////////////// | |
24495 // nonmember support // | |
24496 /////////////////////// | |
24497 | |
24498 namespace std // NOLINT(cert-dcl58-cpp) | |
24499 { | |
24500 | |
24501 /// @brief hash value for JSON objects | |
24502 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ | |
24503 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
24504 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp) | |
24505 { | |
24506 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const | |
24507 { | |
24508 return nlohmann::detail::hash(j); | |
24509 } | |
24510 }; | |
24511 | |
24512 // specialization for std::less<value_t> | |
24513 template<> | |
24514 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 | |
24515 { | |
24516 /*! | |
24517 @brief compare two value_t enum values | |
24518 @since version 3.0.0 | |
24519 */ | |
24520 bool operator()(::nlohmann::detail::value_t lhs, | |
24521 ::nlohmann::detail::value_t rhs) const noexcept | |
24522 { | |
24523 #if JSON_HAS_THREE_WAY_COMPARISON | |
24524 return std::is_lt(lhs <=> rhs); // *NOPAD* | |
24525 #else | |
24526 return ::nlohmann::detail::operator<(lhs, rhs); | |
24527 #endif | |
24528 } | |
24529 }; | |
24530 | |
24531 // C++20 prohibit function specialization in the std namespace. | |
24532 #ifndef JSON_HAS_CPP_20 | |
24533 | |
24534 /// @brief exchanges the values of two JSON objects | |
24535 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ | |
24536 NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
24537 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) | |
24538 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) | |
24539 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) | |
24540 { | |
24541 j1.swap(j2); | |
24542 } | |
24543 | |
24544 #endif | |
24545 | |
24546 } // namespace std | |
24547 | |
24548 #if JSON_USE_GLOBAL_UDLS | |
24549 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) | |
24550 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) | |
24551 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) | |
24552 #else | |
24553 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) | |
24554 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) | |
24555 #endif | |
24556 #endif | |
24557 | |
24558 // #include <nlohmann/detail/macro_unscope.hpp> | |
24559 // __ _____ _____ _____ | |
24560 // __| | __| | | | JSON for Modern C++ | |
24561 // | | |__ | | | | | | version 3.11.3 | |
24562 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
24563 // | |
24564 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
24565 // SPDX-License-Identifier: MIT | |
24566 | |
24567 | |
24568 | |
24569 // restore clang diagnostic settings | |
24570 #if defined(__clang__) | |
24571 #pragma clang diagnostic pop | |
24572 #endif | |
24573 | |
24574 // clean up | |
24575 #undef JSON_ASSERT | |
24576 #undef JSON_INTERNAL_CATCH | |
24577 #undef JSON_THROW | |
24578 #undef JSON_PRIVATE_UNLESS_TESTED | |
24579 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION | |
24580 #undef NLOHMANN_BASIC_JSON_TPL | |
24581 #undef JSON_EXPLICIT | |
24582 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL | |
24583 #undef JSON_INLINE_VARIABLE | |
24584 #undef JSON_NO_UNIQUE_ADDRESS | |
24585 #undef JSON_DISABLE_ENUM_SERIALIZATION | |
24586 #undef JSON_USE_GLOBAL_UDLS | |
24587 | |
24588 #ifndef JSON_TEST_KEEP_MACROS | |
24589 #undef JSON_CATCH | |
24590 #undef JSON_TRY | |
24591 #undef JSON_HAS_CPP_11 | |
24592 #undef JSON_HAS_CPP_14 | |
24593 #undef JSON_HAS_CPP_17 | |
24594 #undef JSON_HAS_CPP_20 | |
24595 #undef JSON_HAS_FILESYSTEM | |
24596 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM | |
24597 #undef JSON_HAS_THREE_WAY_COMPARISON | |
24598 #undef JSON_HAS_RANGES | |
24599 #undef JSON_HAS_STATIC_RTTI | |
24600 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON | |
24601 #endif | |
24602 | |
24603 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> | |
24604 // __ _____ _____ _____ | |
24605 // __| | __| | | | JSON for Modern C++ | |
24606 // | | |__ | | | | | | version 3.11.3 | |
24607 // |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
24608 // | |
24609 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> | |
24610 // SPDX-License-Identifier: MIT | |
24611 | |
24612 | |
24613 | |
24614 #undef JSON_HEDLEY_ALWAYS_INLINE | |
24615 #undef JSON_HEDLEY_ARM_VERSION | |
24616 #undef JSON_HEDLEY_ARM_VERSION_CHECK | |
24617 #undef JSON_HEDLEY_ARRAY_PARAM | |
24618 #undef JSON_HEDLEY_ASSUME | |
24619 #undef JSON_HEDLEY_BEGIN_C_DECLS | |
24620 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE | |
24621 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN | |
24622 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE | |
24623 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE | |
24624 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION | |
24625 #undef JSON_HEDLEY_CLANG_HAS_FEATURE | |
24626 #undef JSON_HEDLEY_CLANG_HAS_WARNING | |
24627 #undef JSON_HEDLEY_COMPCERT_VERSION | |
24628 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK | |
24629 #undef JSON_HEDLEY_CONCAT | |
24630 #undef JSON_HEDLEY_CONCAT3 | |
24631 #undef JSON_HEDLEY_CONCAT3_EX | |
24632 #undef JSON_HEDLEY_CONCAT_EX | |
24633 #undef JSON_HEDLEY_CONST | |
24634 #undef JSON_HEDLEY_CONSTEXPR | |
24635 #undef JSON_HEDLEY_CONST_CAST | |
24636 #undef JSON_HEDLEY_CPP_CAST | |
24637 #undef JSON_HEDLEY_CRAY_VERSION | |
24638 #undef JSON_HEDLEY_CRAY_VERSION_CHECK | |
24639 #undef JSON_HEDLEY_C_DECL | |
24640 #undef JSON_HEDLEY_DEPRECATED | |
24641 #undef JSON_HEDLEY_DEPRECATED_FOR | |
24642 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL | |
24643 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ | |
24644 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED | |
24645 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES | |
24646 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS | |
24647 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION | |
24648 #undef JSON_HEDLEY_DIAGNOSTIC_POP | |
24649 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH | |
24650 #undef JSON_HEDLEY_DMC_VERSION | |
24651 #undef JSON_HEDLEY_DMC_VERSION_CHECK | |
24652 #undef JSON_HEDLEY_EMPTY_BASES | |
24653 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION | |
24654 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK | |
24655 #undef JSON_HEDLEY_END_C_DECLS | |
24656 #undef JSON_HEDLEY_FLAGS | |
24657 #undef JSON_HEDLEY_FLAGS_CAST | |
24658 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE | |
24659 #undef JSON_HEDLEY_GCC_HAS_BUILTIN | |
24660 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE | |
24661 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE | |
24662 #undef JSON_HEDLEY_GCC_HAS_EXTENSION | |
24663 #undef JSON_HEDLEY_GCC_HAS_FEATURE | |
24664 #undef JSON_HEDLEY_GCC_HAS_WARNING | |
24665 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK | |
24666 #undef JSON_HEDLEY_GCC_VERSION | |
24667 #undef JSON_HEDLEY_GCC_VERSION_CHECK | |
24668 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE | |
24669 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN | |
24670 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE | |
24671 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE | |
24672 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION | |
24673 #undef JSON_HEDLEY_GNUC_HAS_FEATURE | |
24674 #undef JSON_HEDLEY_GNUC_HAS_WARNING | |
24675 #undef JSON_HEDLEY_GNUC_VERSION | |
24676 #undef JSON_HEDLEY_GNUC_VERSION_CHECK | |
24677 #undef JSON_HEDLEY_HAS_ATTRIBUTE | |
24678 #undef JSON_HEDLEY_HAS_BUILTIN | |
24679 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE | |
24680 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS | |
24681 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE | |
24682 #undef JSON_HEDLEY_HAS_EXTENSION | |
24683 #undef JSON_HEDLEY_HAS_FEATURE | |
24684 #undef JSON_HEDLEY_HAS_WARNING | |
24685 #undef JSON_HEDLEY_IAR_VERSION | |
24686 #undef JSON_HEDLEY_IAR_VERSION_CHECK | |
24687 #undef JSON_HEDLEY_IBM_VERSION | |
24688 #undef JSON_HEDLEY_IBM_VERSION_CHECK | |
24689 #undef JSON_HEDLEY_IMPORT | |
24690 #undef JSON_HEDLEY_INLINE | |
24691 #undef JSON_HEDLEY_INTEL_CL_VERSION | |
24692 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK | |
24693 #undef JSON_HEDLEY_INTEL_VERSION | |
24694 #undef JSON_HEDLEY_INTEL_VERSION_CHECK | |
24695 #undef JSON_HEDLEY_IS_CONSTANT | |
24696 #undef JSON_HEDLEY_IS_CONSTEXPR_ | |
24697 #undef JSON_HEDLEY_LIKELY | |
24698 #undef JSON_HEDLEY_MALLOC | |
24699 #undef JSON_HEDLEY_MCST_LCC_VERSION | |
24700 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK | |
24701 #undef JSON_HEDLEY_MESSAGE | |
24702 #undef JSON_HEDLEY_MSVC_VERSION | |
24703 #undef JSON_HEDLEY_MSVC_VERSION_CHECK | |
24704 #undef JSON_HEDLEY_NEVER_INLINE | |
24705 #undef JSON_HEDLEY_NON_NULL | |
24706 #undef JSON_HEDLEY_NO_ESCAPE | |
24707 #undef JSON_HEDLEY_NO_RETURN | |
24708 #undef JSON_HEDLEY_NO_THROW | |
24709 #undef JSON_HEDLEY_NULL | |
24710 #undef JSON_HEDLEY_PELLES_VERSION | |
24711 #undef JSON_HEDLEY_PELLES_VERSION_CHECK | |
24712 #undef JSON_HEDLEY_PGI_VERSION | |
24713 #undef JSON_HEDLEY_PGI_VERSION_CHECK | |
24714 #undef JSON_HEDLEY_PREDICT | |
24715 #undef JSON_HEDLEY_PRINTF_FORMAT | |
24716 #undef JSON_HEDLEY_PRIVATE | |
24717 #undef JSON_HEDLEY_PUBLIC | |
24718 #undef JSON_HEDLEY_PURE | |
24719 #undef JSON_HEDLEY_REINTERPRET_CAST | |
24720 #undef JSON_HEDLEY_REQUIRE | |
24721 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR | |
24722 #undef JSON_HEDLEY_REQUIRE_MSG | |
24723 #undef JSON_HEDLEY_RESTRICT | |
24724 #undef JSON_HEDLEY_RETURNS_NON_NULL | |
24725 #undef JSON_HEDLEY_SENTINEL | |
24726 #undef JSON_HEDLEY_STATIC_ASSERT | |
24727 #undef JSON_HEDLEY_STATIC_CAST | |
24728 #undef JSON_HEDLEY_STRINGIFY | |
24729 #undef JSON_HEDLEY_STRINGIFY_EX | |
24730 #undef JSON_HEDLEY_SUNPRO_VERSION | |
24731 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK | |
24732 #undef JSON_HEDLEY_TINYC_VERSION | |
24733 #undef JSON_HEDLEY_TINYC_VERSION_CHECK | |
24734 #undef JSON_HEDLEY_TI_ARMCL_VERSION | |
24735 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK | |
24736 #undef JSON_HEDLEY_TI_CL2000_VERSION | |
24737 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK | |
24738 #undef JSON_HEDLEY_TI_CL430_VERSION | |
24739 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK | |
24740 #undef JSON_HEDLEY_TI_CL6X_VERSION | |
24741 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK | |
24742 #undef JSON_HEDLEY_TI_CL7X_VERSION | |
24743 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK | |
24744 #undef JSON_HEDLEY_TI_CLPRU_VERSION | |
24745 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK | |
24746 #undef JSON_HEDLEY_TI_VERSION | |
24747 #undef JSON_HEDLEY_TI_VERSION_CHECK | |
24748 #undef JSON_HEDLEY_UNAVAILABLE | |
24749 #undef JSON_HEDLEY_UNLIKELY | |
24750 #undef JSON_HEDLEY_UNPREDICTABLE | |
24751 #undef JSON_HEDLEY_UNREACHABLE | |
24752 #undef JSON_HEDLEY_UNREACHABLE_RETURN | |
24753 #undef JSON_HEDLEY_VERSION | |
24754 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR | |
24755 #undef JSON_HEDLEY_VERSION_DECODE_MINOR | |
24756 #undef JSON_HEDLEY_VERSION_DECODE_REVISION | |
24757 #undef JSON_HEDLEY_VERSION_ENCODE | |
24758 #undef JSON_HEDLEY_WARNING | |
24759 #undef JSON_HEDLEY_WARN_UNUSED_RESULT | |
24760 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG | |
24761 #undef JSON_HEDLEY_FALL_THROUGH | |
24762 | |
24763 | |
24764 | |
24765 #endif // INCLUDE_NLOHMANN_JSON_HPP_ |