AlgoPlus v0.1.0
Loading...
Searching...
No Matches
json.hpp
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#include <utility>
44
45// #include <nlohmann/detail/abi_macros.hpp>
46// __ _____ _____ _____
47// __| | __| | | | JSON for Modern C++
48// | | |__ | | | | | | version 3.11.3
49// |_____|_____|_____|_|___| https://github.com/nlohmann/json
50//
51// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
52// SPDX-License-Identifier: MIT
53
54// This file contains all macro definitions affecting or depending on the ABI
55
56#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
57#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && \
58 defined(NLOHMANN_JSON_VERSION_PATCH)
59#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || \
60 NLOHMANN_JSON_VERSION_PATCH != 3
61#warning "Already included a different version of the library!"
62#endif
63#endif
64#endif
65
66#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
67#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
68#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
69
70#ifndef JSON_DIAGNOSTICS
71#define JSON_DIAGNOSTICS 0
72#endif
73
74#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
75#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
76#endif
77
78#if JSON_DIAGNOSTICS
79#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
80#else
81#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
82#endif
83
84#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
85#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
86#else
87#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
88#endif
89
90#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
91#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
92#endif
93
94// Construct the namespace ABI tags component
95#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b
96#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
97
98#define NLOHMANN_JSON_ABI_TAGS \
99 NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
100 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
101
102// Construct the namespace version component
103#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch
104#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
105 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
106
107#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
108#define NLOHMANN_JSON_NAMESPACE_VERSION
109#else
110#define NLOHMANN_JSON_NAMESPACE_VERSION \
111 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT( \
112 NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH)
113#endif
114
115// Combine namespace components
116#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b
117#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
118
119#ifndef NLOHMANN_JSON_NAMESPACE
120#define NLOHMANN_JSON_NAMESPACE \
121 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, \
122 NLOHMANN_JSON_NAMESPACE_VERSION)
123#endif
124
125#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
126#define NLOHMANN_JSON_NAMESPACE_BEGIN \
127 namespace nlohmann { \
128 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, \
129 NLOHMANN_JSON_NAMESPACE_VERSION) {
130#endif
131
132#ifndef NLOHMANN_JSON_NAMESPACE_END
133#define NLOHMANN_JSON_NAMESPACE_END \
134 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
135 } // namespace nlohmann
136#endif
137
138// #include <nlohmann/detail/conversions/from_json.hpp>
139// __ _____ _____ _____
140// __| | __| | | | JSON for Modern C++
141// | | |__ | | | | | | version 3.11.3
142// |_____|_____|_____|_|___| https://github.com/nlohmann/json
143//
144// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
145// SPDX-License-Identifier: MIT
146
147#include <algorithm> // transform
148#include <array> // array
149#include <forward_list> // forward_list
150#include <iterator> // inserter, front_inserter, end
151#include <map> // map
152#include <string> // string
153#include <tuple> // tuple, make_tuple
154#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
155#include <unordered_map> // unordered_map
156#include <utility> // pair, declval
157#include <valarray> // valarray
158
159// #include <nlohmann/detail/exceptions.hpp>
160// __ _____ _____ _____
161// __| | __| | | | JSON for Modern C++
162// | | |__ | | | | | | version 3.11.3
163// |_____|_____|_____|_|___| https://github.com/nlohmann/json
164//
165// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
166// SPDX-License-Identifier: MIT
167
168#include <cstddef> // nullptr_t
169#include <exception> // exception
170#if JSON_DIAGNOSTICS
171#include <numeric> // accumulate
172#endif
173#include <stdexcept> // runtime_error
174#include <string> // to_string
175#include <vector> // vector
176
177// #include <nlohmann/detail/value_t.hpp>
178// __ _____ _____ _____
179// __| | __| | | | JSON for Modern C++
180// | | |__ | | | | | | version 3.11.3
181// |_____|_____|_____|_|___| https://github.com/nlohmann/json
182//
183// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
184// SPDX-License-Identifier: MIT
185
186#include <array> // array
187#include <cstddef> // size_t
188#include <cstdint> // uint8_t
189#include <string> // string
190
191// #include <nlohmann/detail/macro_scope.hpp>
192// __ _____ _____ _____
193// __| | __| | | | JSON for Modern C++
194// | | |__ | | | | | | version 3.11.3
195// |_____|_____|_____|_|___| https://github.com/nlohmann/json
196//
197// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
198// SPDX-License-Identifier: MIT
199
200#include <utility> // declval, pair
201// #include <nlohmann/detail/meta/detected.hpp>
202// __ _____ _____ _____
203// __| | __| | | | JSON for Modern C++
204// | | |__ | | | | | | version 3.11.3
205// |_____|_____|_____|_|___| https://github.com/nlohmann/json
206//
207// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
208// SPDX-License-Identifier: MIT
209
210#include <type_traits>
211
212// #include <nlohmann/detail/meta/void_t.hpp>
213// __ _____ _____ _____
214// __| | __| | | | JSON for Modern C++
215// | | |__ | | | | | | version 3.11.3
216// |_____|_____|_____|_|___| https://github.com/nlohmann/json
217//
218// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
219// SPDX-License-Identifier: MIT
220
221// #include <nlohmann/detail/abi_macros.hpp>
222
223NLOHMANN_JSON_NAMESPACE_BEGIN
224namespace detail {
225
226template <typename... Ts> struct make_void {
227 using type = void;
228};
229template <typename... Ts> using void_t = typename make_void<Ts...>::type;
230
231} // namespace detail
232NLOHMANN_JSON_NAMESPACE_END
233
234NLOHMANN_JSON_NAMESPACE_BEGIN
235namespace detail {
236
237// https://en.cppreference.com/w/cpp/experimental/is_detected
238struct nonesuch {
239 nonesuch() = delete;
240 ~nonesuch() = delete;
241 nonesuch(nonesuch const&) = delete;
242 nonesuch(nonesuch const&&) = delete;
243 void operator=(nonesuch const&) = delete;
244 void operator=(nonesuch&&) = delete;
245};
246
247template <class Default, class AlwaysVoid, template <class...> class Op, class... Args>
248struct detector {
249 using value_t = std::false_type;
250 using type = Default;
251};
252
253template <class Default, template <class...> class Op, class... Args>
254struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
255 using value_t = std::true_type;
256 using type = Op<Args...>;
257};
258
259template <template <class...> class Op, class... Args>
260using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
261
262template <template <class...> class Op, class... Args>
263struct is_detected_lazy : is_detected<Op, Args...> {};
264
265template <template <class...> class Op, class... Args>
266using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
267
268template <class Default, template <class...> class Op, class... Args>
269using detected_or = detector<Default, void, Op, Args...>;
270
271template <class Default, template <class...> class Op, class... Args>
272using detected_or_t = typename detected_or<Default, Op, Args...>::type;
273
274template <class Expected, template <class...> class Op, class... Args>
275using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
276
277template <class To, template <class...> class Op, class... Args>
278using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
279
280} // namespace detail
281NLOHMANN_JSON_NAMESPACE_END
282
283// #include <nlohmann/thirdparty/hedley/hedley.hpp>
284
285// __ _____ _____ _____
286// __| | __| | | | JSON for Modern C++
287// | | |__ | | | | | | version 3.11.3
288// |_____|_____|_____|_|___| https://github.com/nlohmann/json
289//
290// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
291// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
292// SPDX-License-Identifier: MIT
293
294/* Hedley - https://nemequ.github.io/hedley
295 * Created by Evan Nemerson <evan@nemerson.com>
296 */
297
298#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
299#if defined(JSON_HEDLEY_VERSION)
300#undef JSON_HEDLEY_VERSION
301#endif
302#define JSON_HEDLEY_VERSION 15
303
304#if defined(JSON_HEDLEY_STRINGIFY_EX)
305#undef JSON_HEDLEY_STRINGIFY_EX
306#endif
307#define JSON_HEDLEY_STRINGIFY_EX(x) #x
308
309#if defined(JSON_HEDLEY_STRINGIFY)
310#undef JSON_HEDLEY_STRINGIFY
311#endif
312#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
313
314#if defined(JSON_HEDLEY_CONCAT_EX)
315#undef JSON_HEDLEY_CONCAT_EX
316#endif
317#define JSON_HEDLEY_CONCAT_EX(a, b) a##b
318
319#if defined(JSON_HEDLEY_CONCAT)
320#undef JSON_HEDLEY_CONCAT
321#endif
322#define JSON_HEDLEY_CONCAT(a, b) JSON_HEDLEY_CONCAT_EX(a, b)
323
324#if defined(JSON_HEDLEY_CONCAT3_EX)
325#undef JSON_HEDLEY_CONCAT3_EX
326#endif
327#define JSON_HEDLEY_CONCAT3_EX(a, b, c) a##b##c
328
329#if defined(JSON_HEDLEY_CONCAT3)
330#undef JSON_HEDLEY_CONCAT3
331#endif
332#define JSON_HEDLEY_CONCAT3(a, b, c) JSON_HEDLEY_CONCAT3_EX(a, b, c)
333
334#if defined(JSON_HEDLEY_VERSION_ENCODE)
335#undef JSON_HEDLEY_VERSION_ENCODE
336#endif
337#define JSON_HEDLEY_VERSION_ENCODE(major, minor, revision) \
338 (((major) * 1000000) + ((minor) * 1000) + (revision))
339
340#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
341#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
342#endif
343#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
344
345#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
346#undef JSON_HEDLEY_VERSION_DECODE_MINOR
347#endif
348#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
349
350#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
351#undef JSON_HEDLEY_VERSION_DECODE_REVISION
352#endif
353#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
354
355#if defined(JSON_HEDLEY_GNUC_VERSION)
356#undef JSON_HEDLEY_GNUC_VERSION
357#endif
358#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
359#define JSON_HEDLEY_GNUC_VERSION \
360 JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
361#elif defined(__GNUC__)
362#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
363#endif
364
365#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
366#undef JSON_HEDLEY_GNUC_VERSION_CHECK
367#endif
368#if defined(JSON_HEDLEY_GNUC_VERSION)
369#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) \
370 (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
371#else
372#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) (0)
373#endif
374
375#if defined(JSON_HEDLEY_MSVC_VERSION)
376#undef JSON_HEDLEY_MSVC_VERSION
377#endif
378#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
379#define JSON_HEDLEY_MSVC_VERSION \
380 JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, \
381 (_MSC_FULL_VER % 100000) / 100)
382#elif defined(_MSC_FULL_VER) && !defined(__ICL)
383#define JSON_HEDLEY_MSVC_VERSION \
384 JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, \
385 (_MSC_FULL_VER % 10000) / 10)
386#elif defined(_MSC_VER) && !defined(__ICL)
387#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
388#endif
389
390#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
391#undef JSON_HEDLEY_MSVC_VERSION_CHECK
392#endif
393#if !defined(JSON_HEDLEY_MSVC_VERSION)
394#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (0)
395#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
396#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \
397 (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
398#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
399#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) \
400 (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
401#else
402#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (_MSC_VER >= ((major * 100) + (minor)))
403#endif
404
405#if defined(JSON_HEDLEY_INTEL_VERSION)
406#undef JSON_HEDLEY_INTEL_VERSION
407#endif
408#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
409#define JSON_HEDLEY_INTEL_VERSION \
410 JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, \
411 __INTEL_COMPILER_UPDATE)
412#elif defined(__INTEL_COMPILER) && !defined(__ICL)
413#define JSON_HEDLEY_INTEL_VERSION \
414 JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
415#endif
416
417#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
418#undef JSON_HEDLEY_INTEL_VERSION_CHECK
419#endif
420#if defined(JSON_HEDLEY_INTEL_VERSION)
421#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) \
422 (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
423#else
424#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) (0)
425#endif
426
427#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
428#undef JSON_HEDLEY_INTEL_CL_VERSION
429#endif
430#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
431#define JSON_HEDLEY_INTEL_CL_VERSION \
432 JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
433#endif
434
435#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
436#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
437#endif
438#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
439#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) \
440 (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
441#else
442#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major, minor, patch) (0)
443#endif
444
445#if defined(JSON_HEDLEY_PGI_VERSION)
446#undef JSON_HEDLEY_PGI_VERSION
447#endif
448#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
449#define JSON_HEDLEY_PGI_VERSION \
450 JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
451#endif
452
453#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
454#undef JSON_HEDLEY_PGI_VERSION_CHECK
455#endif
456#if defined(JSON_HEDLEY_PGI_VERSION)
457#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) \
458 (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
459#else
460#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (0)
461#endif
462
463#if defined(JSON_HEDLEY_SUNPRO_VERSION)
464#undef JSON_HEDLEY_SUNPRO_VERSION
465#endif
466#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
467#define JSON_HEDLEY_SUNPRO_VERSION \
468 JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \
469 (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \
470 (__SUNPRO_C & 0xf) * 10)
471#elif defined(__SUNPRO_C)
472#define JSON_HEDLEY_SUNPRO_VERSION \
473 JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
474#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
475#define JSON_HEDLEY_SUNPRO_VERSION \
476 JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \
477 (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \
478 (__SUNPRO_CC & 0xf) * 10)
479#elif defined(__SUNPRO_CC)
480#define JSON_HEDLEY_SUNPRO_VERSION \
481 JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, \
482 (__SUNPRO_CC) & 0xf)
483#endif
484
485#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
486#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
487#endif
488#if defined(JSON_HEDLEY_SUNPRO_VERSION)
489#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) \
490 (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
491#else
492#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) (0)
493#endif
494
495#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
496#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
497#endif
498#if defined(__EMSCRIPTEN__)
499#define JSON_HEDLEY_EMSCRIPTEN_VERSION \
500 JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
501#endif
502
503#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
504#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
505#endif
506#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
507#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) \
508 (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
509#else
510#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) (0)
511#endif
512
513#if defined(JSON_HEDLEY_ARM_VERSION)
514#undef JSON_HEDLEY_ARM_VERSION
515#endif
516#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
517#define JSON_HEDLEY_ARM_VERSION \
518 JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, \
519 (__ARMCOMPILER_VERSION % 1000000) / 10000, \
520 (__ARMCOMPILER_VERSION % 10000) / 100)
521#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
522#define JSON_HEDLEY_ARM_VERSION \
523 JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, \
524 (__ARMCC_VERSION % 10000) / 100)
525#endif
526
527#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
528#undef JSON_HEDLEY_ARM_VERSION_CHECK
529#endif
530#if defined(JSON_HEDLEY_ARM_VERSION)
531#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) \
532 (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
533#else
534#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (0)
535#endif
536
537#if defined(JSON_HEDLEY_IBM_VERSION)
538#undef JSON_HEDLEY_IBM_VERSION
539#endif
540#if defined(__ibmxl__)
541#define JSON_HEDLEY_IBM_VERSION \
542 JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
543#elif defined(__xlC__) && defined(__xlC_ver__)
544#define JSON_HEDLEY_IBM_VERSION \
545 JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
546#elif defined(__xlC__)
547#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
548#endif
549
550#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
551#undef JSON_HEDLEY_IBM_VERSION_CHECK
552#endif
553#if defined(JSON_HEDLEY_IBM_VERSION)
554#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) \
555 (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
556#else
557#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (0)
558#endif
559
560#if defined(JSON_HEDLEY_TI_VERSION)
561#undef JSON_HEDLEY_TI_VERSION
562#endif
563#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__) || \
564 defined(__MSP430__) || defined(__TMS320C2000__))
565#if (__TI_COMPILER_VERSION__ >= 16000000)
566#define JSON_HEDLEY_TI_VERSION \
567 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
568 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
569 (__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) \
578 (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
579#else
580#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) (0)
581#endif
582
583#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
584#undef JSON_HEDLEY_TI_CL2000_VERSION
585#endif
586#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
587#define JSON_HEDLEY_TI_CL2000_VERSION \
588 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
589 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
590 (__TI_COMPILER_VERSION__ % 1000))
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
594#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
595#endif
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) \
598 (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
599#else
600#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) (0)
601#endif
602
603#if defined(JSON_HEDLEY_TI_CL430_VERSION)
604#undef JSON_HEDLEY_TI_CL430_VERSION
605#endif
606#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
607#define JSON_HEDLEY_TI_CL430_VERSION \
608 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
609 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
610 (__TI_COMPILER_VERSION__ % 1000))
611#endif
612
613#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
614#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
615#endif
616#if defined(JSON_HEDLEY_TI_CL430_VERSION)
617#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) \
618 (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
619#else
620#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) (0)
621#endif
622
623#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
624#undef JSON_HEDLEY_TI_ARMCL_VERSION
625#endif
626#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
627#define JSON_HEDLEY_TI_ARMCL_VERSION \
628 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
629 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
630 (__TI_COMPILER_VERSION__ % 1000))
631#endif
632
633#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
634#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
635#endif
636#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
637#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) \
638 (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
639#else
640#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) (0)
641#endif
642
643#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
644#undef JSON_HEDLEY_TI_CL6X_VERSION
645#endif
646#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
647#define JSON_HEDLEY_TI_CL6X_VERSION \
648 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
649 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
650 (__TI_COMPILER_VERSION__ % 1000))
651#endif
652
653#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
654#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
655#endif
656#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
657#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) \
658 (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
659#else
660#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) (0)
661#endif
662
663#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
664#undef JSON_HEDLEY_TI_CL7X_VERSION
665#endif
666#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
667#define JSON_HEDLEY_TI_CL7X_VERSION \
668 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
669 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
670 (__TI_COMPILER_VERSION__ % 1000))
671#endif
672
673#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
674#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
675#endif
676#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
677#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) \
678 (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
679#else
680#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) (0)
681#endif
682
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
684#undef JSON_HEDLEY_TI_CLPRU_VERSION
685#endif
686#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
687#define JSON_HEDLEY_TI_CLPRU_VERSION \
688 JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, \
689 (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
690 (__TI_COMPILER_VERSION__ % 1000))
691#endif
692
693#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
694#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
695#endif
696#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
697#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) \
698 (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
699#else
700#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) (0)
701#endif
702
703#if defined(JSON_HEDLEY_CRAY_VERSION)
704#undef JSON_HEDLEY_CRAY_VERSION
705#endif
706#if defined(_CRAYC)
707#if defined(_RELEASE_PATCHLEVEL)
708#define JSON_HEDLEY_CRAY_VERSION \
709 JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
710#else
711#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
712#endif
713#endif
714
715#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
716#undef JSON_HEDLEY_CRAY_VERSION_CHECK
717#endif
718#if defined(JSON_HEDLEY_CRAY_VERSION)
719#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) \
720 (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
721#else
722#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) (0)
723#endif
724
725#if defined(JSON_HEDLEY_IAR_VERSION)
726#undef JSON_HEDLEY_IAR_VERSION
727#endif
728#if defined(__IAR_SYSTEMS_ICC__)
729#if __VER__ > 1000
730#define JSON_HEDLEY_IAR_VERSION \
731 JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
732#else
733#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
734#endif
735#endif
736
737#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
738#undef JSON_HEDLEY_IAR_VERSION_CHECK
739#endif
740#if defined(JSON_HEDLEY_IAR_VERSION)
741#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) \
742 (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
743#else
744#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (0)
745#endif
746
747#if defined(JSON_HEDLEY_TINYC_VERSION)
748#undef JSON_HEDLEY_TINYC_VERSION
749#endif
750#if defined(__TINYC__)
751#define JSON_HEDLEY_TINYC_VERSION \
752 JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
753#endif
754
755#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
756#undef JSON_HEDLEY_TINYC_VERSION_CHECK
757#endif
758#if defined(JSON_HEDLEY_TINYC_VERSION)
759#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) \
760 (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
761#else
762#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) (0)
763#endif
764
765#if defined(JSON_HEDLEY_DMC_VERSION)
766#undef JSON_HEDLEY_DMC_VERSION
767#endif
768#if defined(__DMC__)
769#define JSON_HEDLEY_DMC_VERSION \
770 JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
771#endif
772
773#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
774#undef JSON_HEDLEY_DMC_VERSION_CHECK
775#endif
776#if defined(JSON_HEDLEY_DMC_VERSION)
777#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) \
778 (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
779#else
780#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (0)
781#endif
782
783#if defined(JSON_HEDLEY_COMPCERT_VERSION)
784#undef JSON_HEDLEY_COMPCERT_VERSION
785#endif
786#if defined(__COMPCERT_VERSION__)
787#define JSON_HEDLEY_COMPCERT_VERSION \
788 JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, \
789 __COMPCERT_VERSION__ % 100)
790#endif
791
792#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
793#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
794#endif
795#if defined(JSON_HEDLEY_COMPCERT_VERSION)
796#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) \
797 (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
798#else
799#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) (0)
800#endif
801
802#if defined(JSON_HEDLEY_PELLES_VERSION)
803#undef JSON_HEDLEY_PELLES_VERSION
804#endif
805#if defined(__POCC__)
806#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
807#endif
808
809#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
810#undef JSON_HEDLEY_PELLES_VERSION_CHECK
811#endif
812#if defined(JSON_HEDLEY_PELLES_VERSION)
813#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) \
814 (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
815#else
816#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) (0)
817#endif
818
819#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
820#undef JSON_HEDLEY_MCST_LCC_VERSION
821#endif
822#if defined(__LCC__) && defined(__LCC_MINOR__)
823#define JSON_HEDLEY_MCST_LCC_VERSION \
824 JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
825#endif
826
827#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
828#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
829#endif
830#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
831#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) \
832 (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
833#else
834#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major, minor, patch) (0)
835#endif
836
837#if defined(JSON_HEDLEY_GCC_VERSION)
838#undef JSON_HEDLEY_GCC_VERSION
839#endif
840#if defined(JSON_HEDLEY_GNUC_VERSION) && !defined(__clang__) && \
841 !defined(JSON_HEDLEY_INTEL_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION) && \
842 !defined(JSON_HEDLEY_ARM_VERSION) && !defined(JSON_HEDLEY_CRAY_VERSION) && \
843 !defined(JSON_HEDLEY_TI_VERSION) && !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
844 !defined(JSON_HEDLEY_TI_CL430_VERSION) && !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
845 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
846 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && !defined(__COMPCERT__) && \
847 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
848#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
849#endif
850
851#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
852#undef JSON_HEDLEY_GCC_VERSION_CHECK
853#endif
854#if defined(JSON_HEDLEY_GCC_VERSION)
855#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) \
856 (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
857#else
858#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (0)
859#endif
860
861#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
862#undef JSON_HEDLEY_HAS_ATTRIBUTE
863#endif
864#if defined(__has_attribute) && \
865 ((!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 5, 9)))
866#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
867#else
868#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
869#endif
870
871#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
872#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
873#endif
874#if defined(__has_attribute)
875#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
876 JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
877#else
878#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
879 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
880#endif
881
882#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
883#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
884#endif
885#if defined(__has_attribute)
886#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
887 JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
888#else
889#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
890 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
891#endif
892
893#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
894#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
895#endif
896#if defined(__has_cpp_attribute) && defined(__cplusplus) && \
897 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0))
898#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
899#else
900#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
901#endif
902
903#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
904#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
905#endif
906#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
907#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0)
908#elif !defined(JSON_HEDLEY_PGI_VERSION) && !defined(JSON_HEDLEY_IAR_VERSION) && \
909 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) && \
910 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19, 20, 0))
911#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
912#else
913#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) (0)
914#endif
915
916#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
917#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
918#endif
919#if defined(__has_cpp_attribute) && defined(__cplusplus)
920#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
921 __has_cpp_attribute(attribute)
922#else
923#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
924 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
925#endif
926
927#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
928#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
929#endif
930#if defined(__has_cpp_attribute) && defined(__cplusplus)
931#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
932 __has_cpp_attribute(attribute)
933#else
934#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) \
935 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
936#endif
937
938#if defined(JSON_HEDLEY_HAS_BUILTIN)
939#undef JSON_HEDLEY_HAS_BUILTIN
940#endif
941#if defined(__has_builtin)
942#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
943#else
944#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
945#endif
946
947#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
948#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
949#endif
950#if defined(__has_builtin)
951#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin)
952#else
953#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \
954 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
955#endif
956
957#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
958#undef JSON_HEDLEY_GCC_HAS_BUILTIN
959#endif
960#if defined(__has_builtin)
961#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) __has_builtin(builtin)
962#else
963#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) \
964 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
965#endif
966
967#if defined(JSON_HEDLEY_HAS_FEATURE)
968#undef JSON_HEDLEY_HAS_FEATURE
969#endif
970#if defined(__has_feature)
971#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
972#else
973#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
974#endif
975
976#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
977#undef JSON_HEDLEY_GNUC_HAS_FEATURE
978#endif
979#if defined(__has_feature)
980#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature)
981#else
982#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) \
983 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
984#endif
985
986#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
987#undef JSON_HEDLEY_GCC_HAS_FEATURE
988#endif
989#if defined(__has_feature)
990#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) __has_feature(feature)
991#else
992#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) \
993 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
994#endif
995
996#if defined(JSON_HEDLEY_HAS_EXTENSION)
997#undef JSON_HEDLEY_HAS_EXTENSION
998#endif
999#if defined(__has_extension)
1000#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
1001#else
1002#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
1003#endif
1004
1005#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
1006#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
1007#endif
1008#if defined(__has_extension)
1009#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension)
1010#else
1011#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) \
1012 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
1013#endif
1014
1015#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
1016#undef JSON_HEDLEY_GCC_HAS_EXTENSION
1017#endif
1018#if defined(__has_extension)
1019#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) __has_extension(extension)
1020#else
1021#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) \
1022 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
1023#endif
1024
1025#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1026#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1027#endif
1028#if defined(__has_declspec_attribute)
1029#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1030#else
1031#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1032#endif
1033
1034#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1035#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1036#endif
1037#if defined(__has_declspec_attribute)
1038#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
1039 __has_declspec_attribute(attribute)
1040#else
1041#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
1042 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
1043#endif
1044
1045#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1046#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1047#endif
1048#if defined(__has_declspec_attribute)
1049#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
1050 __has_declspec_attribute(attribute)
1051#else
1052#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) \
1053 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
1054#endif
1055
1056#if defined(JSON_HEDLEY_HAS_WARNING)
1057#undef JSON_HEDLEY_HAS_WARNING
1058#endif
1059#if defined(__has_warning)
1060#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1061#else
1062#define JSON_HEDLEY_HAS_WARNING(warning) (0)
1063#endif
1064
1065#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1066#undef JSON_HEDLEY_GNUC_HAS_WARNING
1067#endif
1068#if defined(__has_warning)
1069#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning)
1070#else
1071#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) \
1072 JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch)
1073#endif
1074
1075#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1076#undef JSON_HEDLEY_GCC_HAS_WARNING
1077#endif
1078#if defined(__has_warning)
1079#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) __has_warning(warning)
1080#else
1081#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) \
1082 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
1083#endif
1084
1085#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__clang__) || \
1086 JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1087 JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \
1088 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1089 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || \
1090 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 0, 0) || \
1091 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1092 JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 17) || \
1093 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8, 0, 0) || \
1094 (JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) && defined(__C99_PRAGMA_OPERATOR))
1095#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1096#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
1097#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1098#else
1099#define JSON_HEDLEY_PRAGMA(value)
1100#endif
1101
1102#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1103#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1104#endif
1105#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1106#undef JSON_HEDLEY_DIAGNOSTIC_POP
1107#endif
1108#if defined(__clang__)
1109#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1110#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1111#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1112#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1113#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1114#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0)
1115#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1116#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1117#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1118#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1119#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1120#elif JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0)
1121#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1122#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1123#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1124 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 4, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \
1125 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)
1126#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1127#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1128#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0)
1129#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1130#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1131#else
1132#define JSON_HEDLEY_DIAGNOSTIC_PUSH
1133#define JSON_HEDLEY_DIAGNOSTIC_POP
1134#endif
1135
1136/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1137 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1138#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1139#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1140#endif
1141#if defined(__cplusplus)
1142#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1143#if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1144#if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1145#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1146 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1147 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1148 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1149 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1150 xpr JSON_HEDLEY_DIAGNOSTIC_POP
1151#else
1152#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1154 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1155 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") xpr JSON_HEDLEY_DIAGNOSTIC_POP
1156#endif
1157#else
1158#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1159 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1160 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") xpr JSON_HEDLEY_DIAGNOSTIC_POP
1161#endif
1162#endif
1163#endif
1164#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1165#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1166#endif
1167
1168#if defined(JSON_HEDLEY_CONST_CAST)
1169#undef JSON_HEDLEY_CONST_CAST
1170#endif
1171#if defined(__cplusplus)
1172#define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1173#elif JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) || \
1174 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1175#define JSON_HEDLEY_CONST_CAST(T, expr) \
1176 (__extension__({ \
1177 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1178 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL((T)(expr)); \
1179 JSON_HEDLEY_DIAGNOSTIC_POP \
1180 }))
1181#else
1182#define JSON_HEDLEY_CONST_CAST(T, expr) ((T)(expr))
1183#endif
1184
1185#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1186#undef JSON_HEDLEY_REINTERPRET_CAST
1187#endif
1188#if defined(__cplusplus)
1189#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1190#else
1191#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T)(expr))
1192#endif
1193
1194#if defined(JSON_HEDLEY_STATIC_CAST)
1195#undef JSON_HEDLEY_STATIC_CAST
1196#endif
1197#if defined(__cplusplus)
1198#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1199#else
1200#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T)(expr))
1201#endif
1202
1203#if defined(JSON_HEDLEY_CPP_CAST)
1204#undef JSON_HEDLEY_CPP_CAST
1205#endif
1206#if defined(__cplusplus)
1207#if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1208#define JSON_HEDLEY_CPP_CAST(T, expr) \
1209 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1210 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"")((T)(expr)) JSON_HEDLEY_DIAGNOSTIC_POP
1211#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 3, 0)
1212#define JSON_HEDLEY_CPP_CAST(T, expr) \
1213 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1214 _Pragma("diag_suppress=Pe137") JSON_HEDLEY_DIAGNOSTIC_POP
1215#else
1216#define JSON_HEDLEY_CPP_CAST(T, expr) ((T)(expr))
1217#endif
1218#else
1219#define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1220#endif
1221
1222#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1223#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1224#endif
1225#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1226#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \
1227 _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1228#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1229#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1230#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1231#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 1478 1786))
1232#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0)
1233#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1234#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1235#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1236#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0)
1237#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \
1238 _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1239#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
1240#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable : 4996))
1241#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1242#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1243#elif JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1244 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1245 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1246 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1247 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1248 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1249 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1250 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1251 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1252 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0)
1253#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1254#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && !defined(__cplusplus)
1255#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \
1256 _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1257#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) && defined(__cplusplus)
1258#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED \
1259 _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1260#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1261#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1262#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 90, 0)
1263#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1264#else
1265#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1266#endif
1267
1268#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1269#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1270#endif
1271#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1272#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1273 _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1274#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1275#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1276#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1277#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 161))
1278#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1279#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1280#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0)
1281#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
1282 _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1283#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0)
1284#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable : 4068))
1285#elif JSON_HEDLEY_TI_VERSION_CHECK(16, 9, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \
1286 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0)
1287#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1288#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0)
1289#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1290#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1291#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1292#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1293#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1294#else
1295#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1296#endif
1297
1298#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1299#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1300#endif
1301#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1302#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \
1303 _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1304#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0)
1305#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \
1306 _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1307#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0)
1308#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1309#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1310#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 1292))
1311#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 0)
1312#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable : 5030))
1313#elif JSON_HEDLEY_PGI_VERSION_CHECK(20, 7, 0)
1314#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1315#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0)
1316#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1317#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)
1318#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES \
1319 _Pragma("error_messages(off,attrskipunsup)")
1320#elif JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \
1321 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0)
1322#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1323#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1324#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1325#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1326#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1327#else
1328#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1329#endif
1330
1331#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1332#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1333#endif
1334#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1335#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1336#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
1337#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1338#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0)
1339#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1340#else
1341#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1342#endif
1343
1344#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1345#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1346#endif
1347#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1348#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \
1349 _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1350#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0)
1351#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \
1352 _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1353#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1, 0, 0)
1354#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable : 4505))
1355#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1356#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1357#else
1358#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1359#endif
1360
1361#if defined(JSON_HEDLEY_DEPRECATED)
1362#undef JSON_HEDLEY_DEPRECATED
1363#endif
1364#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1365#undef JSON_HEDLEY_DEPRECATED_FOR
1366#endif
1367#if JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1368#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " #since))
1369#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \
1370 __declspec(deprecated("Since " #since "; use " #replacement))
1371#elif (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && \
1372 !defined(JSON_HEDLEY_IAR_VERSION)) || \
1373 JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1374 JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) || \
1375 JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || \
1376 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18, 1, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \
1377 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) || \
1378 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1379#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1380#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \
1381 __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1382#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1383#define JSON_HEDLEY_DEPRECATED(since) \
1384 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1385#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) \
1386 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_( \
1387 [[deprecated("Since " #since "; use " #replacement)]])
1388#elif JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \
1389 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1390 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1391 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1392 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1393 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1394 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1395 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1396 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1397 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1398 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1399 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1400#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1401#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1402#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_PELLES_VERSION_CHECK(6, 50, 0) || \
1403 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1404#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1405#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1406#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1407#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1408#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1409#else
1410#define JSON_HEDLEY_DEPRECATED(since)
1411#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1412#endif
1413
1414#if defined(JSON_HEDLEY_UNAVAILABLE)
1415#undef JSON_HEDLEY_UNAVAILABLE
1416#endif
1417#if JSON_HEDLEY_HAS_ATTRIBUTE(warning) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) || \
1418 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1419#define JSON_HEDLEY_UNAVAILABLE(available_since) \
1420 __attribute__((__warning__("Not available until " #available_since)))
1421#else
1422#define JSON_HEDLEY_UNAVAILABLE(available_since)
1423#endif
1424
1425#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1426#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1427#endif
1428#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1429#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1430#endif
1431#if JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \
1432 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1433 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1434 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1435 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1436 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1437 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1439 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1441 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1442 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \
1443 JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1444#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1445#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1446#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1447#define JSON_HEDLEY_WARN_UNUSED_RESULT \
1448 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1449#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) \
1450 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1451#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1452#define JSON_HEDLEY_WARN_UNUSED_RESULT \
1453 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) \
1455 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1456#elif defined(_Check_return_) /* SAL */
1457#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1458#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1459#else
1460#define JSON_HEDLEY_WARN_UNUSED_RESULT
1461#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1462#endif
1463
1464#if defined(JSON_HEDLEY_SENTINEL)
1465#undef JSON_HEDLEY_SENTINEL
1466#endif
1467#if JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \
1468 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) || \
1469 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1470#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1471#else
1472#define JSON_HEDLEY_SENTINEL(position)
1473#endif
1474
1475#if defined(JSON_HEDLEY_NO_RETURN)
1476#undef JSON_HEDLEY_NO_RETURN
1477#endif
1478#if JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1479#define JSON_HEDLEY_NO_RETURN __noreturn
1480#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1481#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1482#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1483#define JSON_HEDLEY_NO_RETURN _Noreturn
1484#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1485#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1486#elif JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 2, 0) || \
1487 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \
1488 JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1489 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1490 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1491 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1492 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1493 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1494 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1495 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1496 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1497 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1498#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1499#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1500#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1501#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1502#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1503#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)
1504#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1505#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0)
1506#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1507#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0)
1508#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1509#else
1510#define JSON_HEDLEY_NO_RETURN
1511#endif
1512
1513#if defined(JSON_HEDLEY_NO_ESCAPE)
1514#undef JSON_HEDLEY_NO_ESCAPE
1515#endif
1516#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1517#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1518#else
1519#define JSON_HEDLEY_NO_ESCAPE
1520#endif
1521
1522#if defined(JSON_HEDLEY_UNREACHABLE)
1523#undef JSON_HEDLEY_UNREACHABLE
1524#endif
1525#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1526#undef JSON_HEDLEY_UNREACHABLE_RETURN
1527#endif
1528#if defined(JSON_HEDLEY_ASSUME)
1529#undef JSON_HEDLEY_ASSUME
1530#endif
1531#if JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1532 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1533#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1534#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1535#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1536#elif JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0)
1537#if defined(__cplusplus)
1538#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1539#else
1540#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1541#endif
1542#endif
1543#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1544 JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 10, 0) || \
1545 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 5) || \
1546 JSON_HEDLEY_CRAY_VERSION_CHECK(10, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1547#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1548#elif defined(JSON_HEDLEY_ASSUME)
1549#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1550#endif
1551#if !defined(JSON_HEDLEY_ASSUME)
1552#if defined(JSON_HEDLEY_UNREACHABLE)
1553#define JSON_HEDLEY_ASSUME(expr) \
1554 JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1555#else
1556#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1557#endif
1558#endif
1559#if defined(JSON_HEDLEY_UNREACHABLE)
1560#if JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0)
1561#define JSON_HEDLEY_UNREACHABLE_RETURN(value) \
1562 return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1563#else
1564#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1565#endif
1566#else
1567#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1568#endif
1569#if !defined(JSON_HEDLEY_UNREACHABLE)
1570#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1571#endif
1572
1573JSON_HEDLEY_DIAGNOSTIC_PUSH
1574#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1575#pragma clang diagnostic ignored "-Wpedantic"
1576#endif
1577#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1578#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1579#endif
1580#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros", 4, 0, 0)
1581#if defined(__clang__)
1582#pragma clang diagnostic ignored "-Wvariadic-macros"
1583#elif defined(JSON_HEDLEY_GCC_VERSION)
1584#pragma GCC diagnostic ignored "-Wvariadic-macros"
1585#endif
1586#endif
1587#if defined(JSON_HEDLEY_NON_NULL)
1588#undef JSON_HEDLEY_NON_NULL
1589#endif
1590#if JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \
1591 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0)
1592#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1593#else
1594#define JSON_HEDLEY_NON_NULL(...)
1595#endif
1596JSON_HEDLEY_DIAGNOSTIC_POP
1597
1598#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1599#undef JSON_HEDLEY_PRINTF_FORMAT
1600#endif
1601#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && \
1602 !defined(__USE_MINGW_ANSI_STDIO)
1603#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1604 __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1605#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && \
1606 defined(__USE_MINGW_ANSI_STDIO)
1607#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1608 __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1609#elif JSON_HEDLEY_HAS_ATTRIBUTE(format) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \
1610 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \
1611 JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1612 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1613 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1614 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1615 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1616 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1617 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1618 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1619 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1620 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1621#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1622 __attribute__((__format__(__printf__, string_idx, first_to_check)))
1623#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6, 0, 0)
1624#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) \
1625 __declspec(vaformat(printf, string_idx, first_to_check))
1626#else
1627#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check)
1628#endif
1629
1630#if defined(JSON_HEDLEY_CONSTEXPR)
1631#undef JSON_HEDLEY_CONSTEXPR
1632#endif
1633#if defined(__cplusplus)
1634#if __cplusplus >= 201103L
1635#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1636#endif
1637#endif
1638#if !defined(JSON_HEDLEY_CONSTEXPR)
1639#define JSON_HEDLEY_CONSTEXPR
1640#endif
1641
1642#if defined(JSON_HEDLEY_PREDICT)
1643#undef JSON_HEDLEY_PREDICT
1644#endif
1645#if defined(JSON_HEDLEY_LIKELY)
1646#undef JSON_HEDLEY_LIKELY
1647#endif
1648#if defined(JSON_HEDLEY_UNLIKELY)
1649#undef JSON_HEDLEY_UNLIKELY
1650#endif
1651#if defined(JSON_HEDLEY_UNPREDICTABLE)
1652#undef JSON_HEDLEY_UNPREDICTABLE
1653#endif
1654#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1655#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1656#endif
1657#if (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && \
1658 !defined(JSON_HEDLEY_PGI_VERSION)) || \
1659 JSON_HEDLEY_GCC_VERSION_CHECK(9, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1660#define JSON_HEDLEY_PREDICT(expr, value, probability) \
1661 __builtin_expect_with_probability((expr), (value), (probability))
1662#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1663 __builtin_expect_with_probability(!!(expr), 1, (probability))
1664#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1665 __builtin_expect_with_probability(!!(expr), 0, (probability))
1666#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1667#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1668#elif (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1669 JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1670 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \
1671 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1672 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || \
1673 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || \
1674 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1675 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 27) || \
1676 JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1677#define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1678 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) \
1679 : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1680#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1681 (__extension__({ \
1682 double hedley_probability_ = (probability); \
1683 ((hedley_probability_ >= 0.9) \
1684 ? __builtin_expect(!!(expr), 1) \
1685 : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1686 }))
1687#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1688 (__extension__({ \
1689 double hedley_probability_ = (probability); \
1690 ((hedley_probability_ >= 0.9) \
1691 ? __builtin_expect(!!(expr), 0) \
1692 : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1693 }))
1694#define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1695#define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1696#else
1697#define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1698 (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1699#define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1700#define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1701#define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1702#define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1703#endif
1704#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1705#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1706#endif
1707
1708#if defined(JSON_HEDLEY_MALLOC)
1709#undef JSON_HEDLEY_MALLOC
1710#endif
1711#if JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \
1712 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \
1713 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || \
1714 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1715 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1716 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1717 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1718 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1719 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1720 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1721 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1722 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1723 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1724#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1725#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1726#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1727#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1728#define JSON_HEDLEY_MALLOC __declspec(restrict)
1729#else
1730#define JSON_HEDLEY_MALLOC
1731#endif
1732
1733#if defined(JSON_HEDLEY_PURE)
1734#undef JSON_HEDLEY_PURE
1735#endif
1736#if JSON_HEDLEY_HAS_ATTRIBUTE(pure) || JSON_HEDLEY_GCC_VERSION_CHECK(2, 96, 0) || \
1737 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \
1738 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1739 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1740 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1741 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1742 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1743 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1744 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1746 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1748 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \
1749 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1750#define JSON_HEDLEY_PURE __attribute__((__pure__))
1751#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1752#define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1753#elif defined(__cplusplus) && \
1754 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) || \
1755 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0))
1756#define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1757#else
1758#define JSON_HEDLEY_PURE
1759#endif
1760
1761#if defined(JSON_HEDLEY_CONST)
1762#undef JSON_HEDLEY_CONST
1763#endif
1764#if JSON_HEDLEY_HAS_ATTRIBUTE(const) || JSON_HEDLEY_GCC_VERSION_CHECK(2, 5, 0) || \
1765 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \
1766 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1767 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1768 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1770 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1772 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1773 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1774 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1775 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1776 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \
1777 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1778#define JSON_HEDLEY_CONST __attribute__((__const__))
1779#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0)
1780#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1781#else
1782#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1783#endif
1784
1785#if defined(JSON_HEDLEY_RESTRICT)
1786#undef JSON_HEDLEY_RESTRICT
1787#endif
1788#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1789#define JSON_HEDLEY_RESTRICT restrict
1790#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \
1791 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || \
1792 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1793 JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1794 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 4) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \
1795 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1796 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) || \
1797 JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || defined(__clang__) || \
1798 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1799#define JSON_HEDLEY_RESTRICT __restrict
1800#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus)
1801#define JSON_HEDLEY_RESTRICT _Restrict
1802#else
1803#define JSON_HEDLEY_RESTRICT
1804#endif
1805
1806#if defined(JSON_HEDLEY_INLINE)
1807#undef JSON_HEDLEY_INLINE
1808#endif
1809#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1810 (defined(__cplusplus) && (__cplusplus >= 199711L))
1811#define JSON_HEDLEY_INLINE inline
1812#elif defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_ARM_VERSION_CHECK(6, 2, 0)
1813#define JSON_HEDLEY_INLINE __inline__
1814#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || \
1815 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \
1816 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 1, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || \
1817 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 0, 0) || \
1818 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1819 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1820#define JSON_HEDLEY_INLINE __inline
1821#else
1822#define JSON_HEDLEY_INLINE
1823#endif
1824
1825#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1826#undef JSON_HEDLEY_ALWAYS_INLINE
1827#endif
1828#if JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \
1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \
1830 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1831 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1832 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1833 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1834 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1836 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1837 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1838 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1839 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1840 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1842#define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1843#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1844#define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1845#elif defined(__cplusplus) && \
1846 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1847 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \
1848 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0))
1849#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1850#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1851#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1852#else
1853#define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1854#endif
1855
1856#if defined(JSON_HEDLEY_NEVER_INLINE)
1857#undef JSON_HEDLEY_NEVER_INLINE
1858#endif
1859#if JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \
1860 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \
1861 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \
1862 JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \
1863 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \
1865 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \
1867 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1868 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \
1869 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1870 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \
1871 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \
1872 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10) || JSON_HEDLEY_IAR_VERSION_CHECK(8, 10, 0)
1873#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1874#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
1875#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1876#elif JSON_HEDLEY_PGI_VERSION_CHECK(10, 2, 0)
1877#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1878#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)
1879#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1880#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
1881#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1882#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3, 2, 0)
1883#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1884#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9, 0, 0)
1885#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1886#else
1887#define JSON_HEDLEY_NEVER_INLINE
1888#endif
1889
1890#if defined(JSON_HEDLEY_PRIVATE)
1891#undef JSON_HEDLEY_PRIVATE
1892#endif
1893#if defined(JSON_HEDLEY_PUBLIC)
1894#undef JSON_HEDLEY_PUBLIC
1895#endif
1896#if defined(JSON_HEDLEY_IMPORT)
1897#undef JSON_HEDLEY_IMPORT
1898#endif
1899#if defined(_WIN32) || defined(__CYGWIN__)
1900#define JSON_HEDLEY_PRIVATE
1901#define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1902#define JSON_HEDLEY_IMPORT __declspec(dllimport)
1903#else
1904#if JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \
1905 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1906 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \
1907 (defined(__TI_EABI__) && \
1908 ((JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0))) || \
1910 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1911#define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1912#define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1913#else
1914#define JSON_HEDLEY_PRIVATE
1915#define JSON_HEDLEY_PUBLIC
1916#endif
1917#define JSON_HEDLEY_IMPORT extern
1918#endif
1919
1920#if defined(JSON_HEDLEY_NO_THROW)
1921#undef JSON_HEDLEY_NO_THROW
1922#endif
1923#if JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \
1924 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1925#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
1926#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 1, 0) || \
1927 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0)
1928#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
1929#else
1930#define JSON_HEDLEY_NO_THROW
1931#endif
1932
1933#if defined(JSON_HEDLEY_FALL_THROUGH)
1934#undef JSON_HEDLEY_FALL_THROUGH
1935#endif
1936#if JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || JSON_HEDLEY_GCC_VERSION_CHECK(7, 0, 0) || \
1937 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1938#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
1939#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang, fallthrough)
1940#define JSON_HEDLEY_FALL_THROUGH \
1941 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
1942#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
1943#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
1944#elif defined(__fallthrough) /* SAL */
1945#define JSON_HEDLEY_FALL_THROUGH __fallthrough
1946#else
1947#define JSON_HEDLEY_FALL_THROUGH
1948#endif
1949
1950#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
1951#undef JSON_HEDLEY_RETURNS_NON_NULL
1952#endif
1953#if JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || \
1954 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1955#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
1956#elif defined(_Ret_notnull_) /* SAL */
1957#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
1958#else
1959#define JSON_HEDLEY_RETURNS_NON_NULL
1960#endif
1961
1962#if defined(JSON_HEDLEY_ARRAY_PARAM)
1963#undef JSON_HEDLEY_ARRAY_PARAM
1964#endif
1965#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__STDC_NO_VLA__) && \
1966 !defined(__cplusplus) && !defined(JSON_HEDLEY_PGI_VERSION) && \
1967 !defined(JSON_HEDLEY_TINYC_VERSION)
1968#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
1969#else
1970#define JSON_HEDLEY_ARRAY_PARAM(name)
1971#endif
1972
1973#if defined(JSON_HEDLEY_IS_CONSTANT)
1974#undef JSON_HEDLEY_IS_CONSTANT
1975#endif
1976#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
1977#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
1978#endif
1979/* JSON_HEDLEY_IS_CONSTEXPR_ is for
1980 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1981#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
1982#undef JSON_HEDLEY_IS_CONSTEXPR_
1983#endif
1984#if JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \
1985 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 19) || \
1986 JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \
1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \
1988 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) && !defined(__cplusplus)) || \
1989 JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1, 25, 10)
1990#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
1991#endif
1992#if !defined(__cplusplus)
1993#if JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
1994 JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
1995 JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) || \
1996 JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) || JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 24)
1997#if defined(__INTPTR_TYPE__)
1998#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
1999 __builtin_types_compatible_p( \
2000 __typeof__((1 ? (void*)((__INTPTR_TYPE__)((expr) * 0)) : (int*)0)), int*)
2001#else
2002#include <stdint.h>
2003#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
2004 __builtin_types_compatible_p(__typeof__((1 ? (void*)((intptr_t)((expr) * 0)) : (int*)0)), int*)
2005#endif
2006#elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2007 !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION) && \
2008 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2009 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2010 JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) || \
2011 JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || JSON_HEDLEY_ARM_VERSION_CHECK(5, 3, 0)
2012#if defined(__INTPTR_TYPE__)
2013#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
2014 _Generic((1 ? (void*)((__INTPTR_TYPE__)((expr) * 0)) : (int*)0), int*: 1, void*: 0)
2015#else
2016#include <stdint.h>
2017#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
2018 _Generic((1 ? (void*)((intptr_t)*0) : (int*)0), int*: 1, void*: 0)
2019#endif
2020#elif defined(JSON_HEDLEY_GCC_VERSION) || defined(JSON_HEDLEY_INTEL_VERSION) || \
2021 defined(JSON_HEDLEY_TINYC_VERSION) || defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2022 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18, 12, 0) || defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2023 defined(JSON_HEDLEY_TI_CL6X_VERSION) || defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2024 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || defined(__clang__)
2025#define JSON_HEDLEY_IS_CONSTEXPR_(expr) \
2026 (sizeof(void) != \
2027 sizeof(*(1 ? ((void*)((expr) * 0L)) : ((struct { char v[sizeof(void) * 2]; }*)1))))
2028#endif
2029#endif
2030#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2031#if !defined(JSON_HEDLEY_IS_CONSTANT)
2032#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2033#endif
2034#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2035#else
2036#if !defined(JSON_HEDLEY_IS_CONSTANT)
2037#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2038#endif
2039#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2040#endif
2041
2042#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2043#undef JSON_HEDLEY_BEGIN_C_DECLS
2044#endif
2045#if defined(JSON_HEDLEY_END_C_DECLS)
2046#undef JSON_HEDLEY_END_C_DECLS
2047#endif
2048#if defined(JSON_HEDLEY_C_DECL)
2049#undef JSON_HEDLEY_C_DECL
2050#endif
2051#if defined(__cplusplus)
2052#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2053#define JSON_HEDLEY_END_C_DECLS }
2054#define JSON_HEDLEY_C_DECL extern "C"
2055#else
2056#define JSON_HEDLEY_BEGIN_C_DECLS
2057#define JSON_HEDLEY_END_C_DECLS
2058#define JSON_HEDLEY_C_DECL
2059#endif
2060
2061#if defined(JSON_HEDLEY_STATIC_ASSERT)
2062#undef JSON_HEDLEY_STATIC_ASSERT
2063#endif
2064#if !defined(__cplusplus) && \
2065 ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2066 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2067 JSON_HEDLEY_GCC_VERSION_CHECK(6, 0, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \
2068 defined(_Static_assert))
2069#define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2070#elif (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2071 JSON_HEDLEY_MSVC_VERSION_CHECK(16, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
2072#define JSON_HEDLEY_STATIC_ASSERT(expr, message) \
2073 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2074#else
2075#define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2076#endif
2077
2078#if defined(JSON_HEDLEY_NULL)
2079#undef JSON_HEDLEY_NULL
2080#endif
2081#if defined(__cplusplus)
2082#if __cplusplus >= 201103L
2083#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2084#elif defined(NULL)
2085#define JSON_HEDLEY_NULL NULL
2086#else
2087#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2088#endif
2089#elif defined(NULL)
2090#define JSON_HEDLEY_NULL NULL
2091#else
2092#define JSON_HEDLEY_NULL ((void*)0)
2093#endif
2094
2095#if defined(JSON_HEDLEY_MESSAGE)
2096#undef JSON_HEDLEY_MESSAGE
2097#endif
2098#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2099#define JSON_HEDLEY_MESSAGE(msg) \
2100 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2101 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2102 JSON_HEDLEY_PRAGMA(message msg) \
2103 JSON_HEDLEY_DIAGNOSTIC_POP
2104#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 4, 0) || JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
2105#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2106#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0)
2107#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2108#elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0)
2109#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2110#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2, 0, 0)
2111#define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2112#else
2113#define JSON_HEDLEY_MESSAGE(msg)
2114#endif
2115
2116#if defined(JSON_HEDLEY_WARNING)
2117#undef JSON_HEDLEY_WARNING
2118#endif
2119#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2120#define JSON_HEDLEY_WARNING(msg) \
2121 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2122 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2123 JSON_HEDLEY_PRAGMA(clang warning msg) \
2124 JSON_HEDLEY_DIAGNOSTIC_POP
2125#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 8, 0) || JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \
2126 JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0)
2127#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2128#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) || JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
2129#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2130#else
2131#define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2132#endif
2133
2134#if defined(JSON_HEDLEY_REQUIRE)
2135#undef JSON_HEDLEY_REQUIRE
2136#endif
2137#if defined(JSON_HEDLEY_REQUIRE_MSG)
2138#undef JSON_HEDLEY_REQUIRE_MSG
2139#endif
2140#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2141#if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2142#define JSON_HEDLEY_REQUIRE(expr) \
2143 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2144 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2145 __attribute__((diagnose_if(!(expr), #expr, "error"))) JSON_HEDLEY_DIAGNOSTIC_POP
2146#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) \
2147 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2148 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2149 __attribute__((diagnose_if(!(expr), msg, "error"))) JSON_HEDLEY_DIAGNOSTIC_POP
2150#else
2151#define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2152#define JSON_HEDLEY_REQUIRE_MSG(expr, msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2153#endif
2154#else
2155#define JSON_HEDLEY_REQUIRE(expr)
2156#define JSON_HEDLEY_REQUIRE_MSG(expr, msg)
2157#endif
2158
2159#if defined(JSON_HEDLEY_FLAGS)
2160#undef JSON_HEDLEY_FLAGS
2161#endif
2162#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && \
2163 (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2164#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2165#else
2166#define JSON_HEDLEY_FLAGS
2167#endif
2168
2169#if defined(JSON_HEDLEY_FLAGS_CAST)
2170#undef JSON_HEDLEY_FLAGS_CAST
2171#endif
2172#if JSON_HEDLEY_INTEL_VERSION_CHECK(19, 0, 0)
2173#define JSON_HEDLEY_FLAGS_CAST(T, expr) \
2174 (__extension__({ \
2175 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2176 _Pragma("warning(disable:188)")((T)(expr)); \
2177 JSON_HEDLEY_DIAGNOSTIC_POP \
2178 }))
2179#else
2180#define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2181#endif
2182
2183#if defined(JSON_HEDLEY_EMPTY_BASES)
2184#undef JSON_HEDLEY_EMPTY_BASES
2185#endif
2186#if (JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20, 0, 0)) || \
2187 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021, 1, 0)
2188#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2189#else
2190#define JSON_HEDLEY_EMPTY_BASES
2191#endif
2192
2193/* Remaining macros are deprecated. */
2194
2195#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2196#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2197#endif
2198#if defined(__clang__)
2199#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) (0)
2200#else
2201#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) \
2202 JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch)
2203#endif
2204
2205#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2206#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2207#endif
2208#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2209
2210#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2211#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2212#endif
2213#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2214
2215#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2216#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2217#endif
2218#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2219
2220#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2221#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2222#endif
2223#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2224
2225#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2226#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2227#endif
2228#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2229
2230#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2231#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2232#endif
2233#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) \
2234 JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2235
2236#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2237#undef JSON_HEDLEY_CLANG_HAS_WARNING
2238#endif
2239#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2240
2241#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2242
2243// This file contains all internal macro definitions (except those affecting
2244// ABI) You MUST include macro_unscope.hpp at the end of json.hpp to undef all
2245// of them
2246
2247// #include <nlohmann/detail/abi_macros.hpp>
2248
2249// exclude unsupported compilers
2250#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2251#if defined(__clang__)
2252#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2253#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2254#endif
2255#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2256#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2257#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2258#endif
2259#endif
2260#endif
2261
2262// C++ language standard detection
2263// if the user manually specified the used c++ version this is skipped
2264#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && \
2265 !defined(JSON_HAS_CPP_11)
2266#if (defined(__cplusplus) && __cplusplus >= 202002L) || \
2267 (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2268#define JSON_HAS_CPP_20
2269#define JSON_HAS_CPP_17
2270#define JSON_HAS_CPP_14
2271#elif (defined(__cplusplus) && __cplusplus >= 201703L) || \
2272 (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2273#define JSON_HAS_CPP_17
2274#define JSON_HAS_CPP_14
2275#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2276#define JSON_HAS_CPP_14
2277#endif
2278// the cpp 11 flag is always specified because it is the minimal required
2279// version
2280#define JSON_HAS_CPP_11
2281#endif
2282
2283#ifdef __has_include
2284#if __has_include(<version>)
2285#include <version>
2286#endif
2287#endif
2288
2289#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2290#ifdef JSON_HAS_CPP_17
2291#if defined(__cpp_lib_filesystem)
2292#define JSON_HAS_FILESYSTEM 1
2293#elif defined(__cpp_lib_experimental_filesystem)
2294#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2295#elif !defined(__has_include)
2296#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2297#elif __has_include(<filesystem>)
2298#define JSON_HAS_FILESYSTEM 1
2299#elif __has_include(<experimental/filesystem>)
2300#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2301#endif
2302
2303// std::filesystem does not work on MinGW GCC 8:
2304// https://sourceforge.net/p/mingw-w64/bugs/737/
2305#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2306#undef JSON_HAS_FILESYSTEM
2307#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2308#endif
2309
2310// no filesystem support before GCC 8:
2311// https://en.cppreference.com/w/cpp/compiler_support
2312#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2313#undef JSON_HAS_FILESYSTEM
2314#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2315#endif
2316
2317// no filesystem support before Clang 7:
2318// https://en.cppreference.com/w/cpp/compiler_support
2319#if defined(__clang_major__) && __clang_major__ < 7
2320#undef JSON_HAS_FILESYSTEM
2321#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2322#endif
2323
2324// no filesystem support before MSVC 19.14:
2325// https://en.cppreference.com/w/cpp/compiler_support
2326#if defined(_MSC_VER) && _MSC_VER < 1914
2327#undef JSON_HAS_FILESYSTEM
2328#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2329#endif
2330
2331// no filesystem support before iOS 13
2332#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2333#undef JSON_HAS_FILESYSTEM
2334#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2335#endif
2336
2337// no filesystem support before macOS Catalina
2338#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2339#undef JSON_HAS_FILESYSTEM
2340#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2341#endif
2342#endif
2343#endif
2344
2345#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2346#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2347#endif
2348
2349#ifndef JSON_HAS_FILESYSTEM
2350#define JSON_HAS_FILESYSTEM 0
2351#endif
2352
2353#ifndef JSON_HAS_THREE_WAY_COMPARISON
2354#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L && \
2355 defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2356#define JSON_HAS_THREE_WAY_COMPARISON 1
2357#else
2358#define JSON_HAS_THREE_WAY_COMPARISON 0
2359#endif
2360#endif
2361
2362#ifndef JSON_HAS_RANGES
2363// ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2364#if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2365#define JSON_HAS_RANGES 0
2366#elif defined(__cpp_lib_ranges)
2367#define JSON_HAS_RANGES 1
2368#else
2369#define JSON_HAS_RANGES 0
2370#endif
2371#endif
2372
2373#ifndef JSON_HAS_STATIC_RTTI
2374#if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2375#define JSON_HAS_STATIC_RTTI 1
2376#else
2377#define JSON_HAS_STATIC_RTTI 0
2378#endif
2379#endif
2380
2381#ifdef JSON_HAS_CPP_17
2382#define JSON_INLINE_VARIABLE inline
2383#else
2384#define JSON_INLINE_VARIABLE
2385#endif
2386
2387#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2388#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2389#else
2390#define JSON_NO_UNIQUE_ADDRESS
2391#endif
2392
2393// disable documentation warnings on clang
2394#if defined(__clang__)
2395#pragma clang diagnostic push
2396#pragma clang diagnostic ignored "-Wdocumentation"
2397#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2398#endif
2399
2400// allow disabling exceptions
2401#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && \
2402 !defined(JSON_NOEXCEPTION)
2403#define JSON_THROW(exception) throw exception
2404#define JSON_TRY try
2405#define JSON_CATCH(exception) catch (exception)
2406#define JSON_INTERNAL_CATCH(exception) catch (exception)
2407#else
2408#include <cstdlib>
2409#define JSON_THROW(exception) std::abort()
2410#define JSON_TRY if (true)
2411#define JSON_CATCH(exception) if (false)
2412#define JSON_INTERNAL_CATCH(exception) if (false)
2413#endif
2414
2415// override exception macros
2416#if defined(JSON_THROW_USER)
2417#undef JSON_THROW
2418#define JSON_THROW JSON_THROW_USER
2419#endif
2420#if defined(JSON_TRY_USER)
2421#undef JSON_TRY
2422#define JSON_TRY JSON_TRY_USER
2423#endif
2424#if defined(JSON_CATCH_USER)
2425#undef JSON_CATCH
2426#define JSON_CATCH JSON_CATCH_USER
2427#undef JSON_INTERNAL_CATCH
2428#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2429#endif
2430#if defined(JSON_INTERNAL_CATCH_USER)
2431#undef JSON_INTERNAL_CATCH
2432#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2433#endif
2434
2435// allow overriding assert
2436#if !defined(JSON_ASSERT)
2437#include <cassert> // assert
2438#define JSON_ASSERT(x) assert(x)
2439#endif
2440
2441// allow to access some private functions (needed by the test suite)
2442#if defined(JSON_TESTS_PRIVATE)
2443#define JSON_PRIVATE_UNLESS_TESTED public
2444#else
2445#define JSON_PRIVATE_UNLESS_TESTED private
2446#endif
2447
2453#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2454 template <typename BasicJsonType> inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) { \
2455 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2456 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2457 auto it = std::find_if(std::begin(m), std::end(m), \
2458 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { \
2459 return ej_pair.first == e; \
2460 }); \
2461 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2462 } \
2463 template <typename BasicJsonType> \
2464 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) { \
2465 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2466 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2467 auto it = std::find_if(std::begin(m), std::end(m), \
2468 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool { \
2469 return ej_pair.second == j; \
2470 }); \
2471 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2472 }
2473
2474// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2475// may be removed in the future once the class is split.
2476
2477#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2478 template <template <typename, typename, typename...> class ObjectType, \
2479 template <typename, typename...> class ArrayType, class StringType, \
2480 class BooleanType, class NumberIntegerType, class NumberUnsignedType, \
2481 class NumberFloatType, template <typename> class AllocatorType, \
2482 template <typename, typename = void> class JSONSerializer, class BinaryType, \
2483 class CustomBaseClass>
2484
2485#define NLOHMANN_BASIC_JSON_TPL \
2486 basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, \
2487 NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType, \
2488 CustomBaseClass>
2489
2490// Macros to simplify conversion from/to types
2491
2492#define NLOHMANN_JSON_EXPAND(x) x
2493#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, \
2494 _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, \
2495 _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, \
2496 _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, \
2497 _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME, ...) \
2498 NAME
2499#define NLOHMANN_JSON_PASTE(...) \
2500 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO( \
2501 __VA_ARGS__, NLOHMANN_JSON_PASTE64, NLOHMANN_JSON_PASTE63, NLOHMANN_JSON_PASTE62, \
2502 NLOHMANN_JSON_PASTE61, NLOHMANN_JSON_PASTE60, NLOHMANN_JSON_PASTE59, \
2503 NLOHMANN_JSON_PASTE58, NLOHMANN_JSON_PASTE57, NLOHMANN_JSON_PASTE56, \
2504 NLOHMANN_JSON_PASTE55, NLOHMANN_JSON_PASTE54, NLOHMANN_JSON_PASTE53, \
2505 NLOHMANN_JSON_PASTE52, NLOHMANN_JSON_PASTE51, NLOHMANN_JSON_PASTE50, \
2506 NLOHMANN_JSON_PASTE49, NLOHMANN_JSON_PASTE48, NLOHMANN_JSON_PASTE47, \
2507 NLOHMANN_JSON_PASTE46, NLOHMANN_JSON_PASTE45, NLOHMANN_JSON_PASTE44, \
2508 NLOHMANN_JSON_PASTE43, NLOHMANN_JSON_PASTE42, NLOHMANN_JSON_PASTE41, \
2509 NLOHMANN_JSON_PASTE40, NLOHMANN_JSON_PASTE39, NLOHMANN_JSON_PASTE38, \
2510 NLOHMANN_JSON_PASTE37, NLOHMANN_JSON_PASTE36, NLOHMANN_JSON_PASTE35, \
2511 NLOHMANN_JSON_PASTE34, NLOHMANN_JSON_PASTE33, NLOHMANN_JSON_PASTE32, \
2512 NLOHMANN_JSON_PASTE31, NLOHMANN_JSON_PASTE30, NLOHMANN_JSON_PASTE29, \
2513 NLOHMANN_JSON_PASTE28, NLOHMANN_JSON_PASTE27, NLOHMANN_JSON_PASTE26, \
2514 NLOHMANN_JSON_PASTE25, NLOHMANN_JSON_PASTE24, NLOHMANN_JSON_PASTE23, \
2515 NLOHMANN_JSON_PASTE22, NLOHMANN_JSON_PASTE21, NLOHMANN_JSON_PASTE20, \
2516 NLOHMANN_JSON_PASTE19, NLOHMANN_JSON_PASTE18, NLOHMANN_JSON_PASTE17, \
2517 NLOHMANN_JSON_PASTE16, NLOHMANN_JSON_PASTE15, NLOHMANN_JSON_PASTE14, \
2518 NLOHMANN_JSON_PASTE13, NLOHMANN_JSON_PASTE12, NLOHMANN_JSON_PASTE11, \
2519 NLOHMANN_JSON_PASTE10, NLOHMANN_JSON_PASTE9, NLOHMANN_JSON_PASTE8, NLOHMANN_JSON_PASTE7, \
2520 NLOHMANN_JSON_PASTE6, NLOHMANN_JSON_PASTE5, NLOHMANN_JSON_PASTE4, NLOHMANN_JSON_PASTE3, \
2521 NLOHMANN_JSON_PASTE2, NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2522#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2523#define NLOHMANN_JSON_PASTE3(func, v1, v2) \
2524 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2525#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) \
2526 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2527#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) \
2528 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2529#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) \
2530 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2531#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) \
2532 NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2533#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) \
2534 NLOHMANN_JSON_PASTE2(func, v1) \
2535 NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2536#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) \
2537 NLOHMANN_JSON_PASTE2(func, v1) \
2538 NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2539#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) \
2540 NLOHMANN_JSON_PASTE2(func, v1) \
2541 NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2542#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
2543 NLOHMANN_JSON_PASTE2(func, v1) \
2544 NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2545#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) \
2546 NLOHMANN_JSON_PASTE2(func, v1) \
2547 NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2548#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) \
2549 NLOHMANN_JSON_PASTE2(func, v1) \
2550 NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2551#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) \
2552 NLOHMANN_JSON_PASTE2(func, v1) \
2553 NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2554#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) \
2555 NLOHMANN_JSON_PASTE2(func, v1) \
2556 NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2557#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2558 v15) \
2559 NLOHMANN_JSON_PASTE2(func, v1) \
2560 NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2561#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2562 v15, v16) \
2563 NLOHMANN_JSON_PASTE2(func, v1) \
2564 NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2565#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2566 v15, v16, v17) \
2567 NLOHMANN_JSON_PASTE2(func, v1) \
2568 NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2569 v17)
2570#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2571 v15, v16, v17, v18) \
2572 NLOHMANN_JSON_PASTE2(func, v1) \
2573 NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2574 v17, v18)
2575#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2576 v15, v16, v17, v18, v19) \
2577 NLOHMANN_JSON_PASTE2(func, v1) \
2578 NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2579 v17, v18, v19)
2580#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2581 v15, v16, v17, v18, v19, v20) \
2582 NLOHMANN_JSON_PASTE2(func, v1) \
2583 NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2584 v17, v18, v19, v20)
2585#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2586 v15, v16, v17, v18, v19, v20, v21) \
2587 NLOHMANN_JSON_PASTE2(func, v1) \
2588 NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2589 v17, v18, v19, v20, v21)
2590#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2591 v15, v16, v17, v18, v19, v20, v21, v22) \
2592 NLOHMANN_JSON_PASTE2(func, v1) \
2593 NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2594 v17, v18, v19, v20, v21, v22)
2595#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2596 v15, v16, v17, v18, v19, v20, v21, v22, v23) \
2597 NLOHMANN_JSON_PASTE2(func, v1) \
2598 NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2599 v17, v18, v19, v20, v21, v22, v23)
2600#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2601 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) \
2602 NLOHMANN_JSON_PASTE2(func, v1) \
2603 NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2604 v17, v18, v19, v20, v21, v22, v23, v24)
2605#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2606 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) \
2607 NLOHMANN_JSON_PASTE2(func, v1) \
2608 NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2609 v17, v18, v19, v20, v21, v22, v23, v24, v25)
2610#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2611 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) \
2612 NLOHMANN_JSON_PASTE2(func, v1) \
2613 NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2614 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2615#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2616 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) \
2617 NLOHMANN_JSON_PASTE2(func, v1) \
2618 NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2619 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2620#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2621 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2622 v28) \
2623 NLOHMANN_JSON_PASTE2(func, v1) \
2624 NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2625 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2626#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2627 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2628 v28, v29) \
2629 NLOHMANN_JSON_PASTE2(func, v1) \
2630 NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2631 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2632#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2633 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2634 v28, v29, v30) \
2635 NLOHMANN_JSON_PASTE2(func, v1) \
2636 NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2637 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2638#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2639 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2640 v28, v29, v30, v31) \
2641 NLOHMANN_JSON_PASTE2(func, v1) \
2642 NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2643 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2644 v31)
2645#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2646 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2647 v28, v29, v30, v31, v32) \
2648 NLOHMANN_JSON_PASTE2(func, v1) \
2649 NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2650 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2651 v31, v32)
2652#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2653 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2654 v28, v29, v30, v31, v32, v33) \
2655 NLOHMANN_JSON_PASTE2(func, v1) \
2656 NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2657 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2658 v31, v32, v33)
2659#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2660 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2661 v28, v29, v30, v31, v32, v33, v34) \
2662 NLOHMANN_JSON_PASTE2(func, v1) \
2663 NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2664 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2665 v31, v32, v33, v34)
2666#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2667 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2668 v28, v29, v30, v31, v32, v33, v34, v35) \
2669 NLOHMANN_JSON_PASTE2(func, v1) \
2670 NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2671 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2672 v31, v32, v33, v34, v35)
2673#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2674 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2675 v28, v29, v30, v31, v32, v33, v34, v35, v36) \
2676 NLOHMANN_JSON_PASTE2(func, v1) \
2677 NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2678 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2679 v31, v32, v33, v34, v35, v36)
2680#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2681 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2682 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) \
2683 NLOHMANN_JSON_PASTE2(func, v1) \
2684 NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2685 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2686 v31, v32, v33, v34, v35, v36, v37)
2687#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2688 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2689 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) \
2690 NLOHMANN_JSON_PASTE2(func, v1) \
2691 NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2692 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2693 v31, v32, v33, v34, v35, v36, v37, v38)
2694#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2695 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2696 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) \
2697 NLOHMANN_JSON_PASTE2(func, v1) \
2698 NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2699 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2700 v31, v32, v33, v34, v35, v36, v37, v38, v39)
2701#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2702 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2703 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) \
2704 NLOHMANN_JSON_PASTE2(func, v1) \
2705 NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2706 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2707 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2708#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2709 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2710 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2711 v41) \
2712 NLOHMANN_JSON_PASTE2(func, v1) \
2713 NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2714 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2715 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2716#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2717 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2718 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2719 v41, v42) \
2720 NLOHMANN_JSON_PASTE2(func, v1) \
2721 NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2722 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2723 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2724#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2725 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2726 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2727 v41, v42, v43) \
2728 NLOHMANN_JSON_PASTE2(func, v1) \
2729 NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2730 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2731 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2732#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2733 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2734 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2735 v41, v42, v43, v44) \
2736 NLOHMANN_JSON_PASTE2(func, v1) \
2737 NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2738 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2739 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2740#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2741 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2742 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2743 v41, v42, v43, v44, v45) \
2744 NLOHMANN_JSON_PASTE2(func, v1) \
2745 NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2746 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2747 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2748 v45)
2749#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2750 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2751 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2752 v41, v42, v43, v44, v45, v46) \
2753 NLOHMANN_JSON_PASTE2(func, v1) \
2754 NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2755 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2756 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2757 v45, v46)
2758#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2759 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2760 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2761 v41, v42, v43, v44, v45, v46, v47) \
2762 NLOHMANN_JSON_PASTE2(func, v1) \
2763 NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2764 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2765 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2766 v45, v46, v47)
2767#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2768 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2769 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2770 v41, v42, v43, v44, v45, v46, v47, v48) \
2771 NLOHMANN_JSON_PASTE2(func, v1) \
2772 NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2773 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2774 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2775 v45, v46, v47, v48)
2776#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2777 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2778 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2779 v41, v42, v43, v44, v45, v46, v47, v48, v49) \
2780 NLOHMANN_JSON_PASTE2(func, v1) \
2781 NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2782 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2783 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2784 v45, v46, v47, v48, v49)
2785#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2786 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2787 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2788 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) \
2789 NLOHMANN_JSON_PASTE2(func, v1) \
2790 NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2791 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2792 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2793 v45, v46, v47, v48, v49, v50)
2794#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2795 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2796 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2797 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) \
2798 NLOHMANN_JSON_PASTE2(func, v1) \
2799 NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2800 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2801 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2802 v45, v46, v47, v48, v49, v50, v51)
2803#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2804 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2805 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2806 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) \
2807 NLOHMANN_JSON_PASTE2(func, v1) \
2808 NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2809 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2810 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2811 v45, v46, v47, v48, v49, v50, v51, v52)
2812#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2813 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2814 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2815 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) \
2816 NLOHMANN_JSON_PASTE2(func, v1) \
2817 NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2818 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2819 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2820 v45, v46, v47, v48, v49, v50, v51, v52, v53)
2821#define NLOHMANN_JSON_PASTE55( \
2822 func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, \
2823 v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2824 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) \
2825 NLOHMANN_JSON_PASTE2(func, v1) \
2826 NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2827 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2828 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2829 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2830#define NLOHMANN_JSON_PASTE56( \
2831 func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, \
2832 v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2833 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) \
2834 NLOHMANN_JSON_PASTE2(func, v1) \
2835 NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2836 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2837 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2838 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2839#define NLOHMANN_JSON_PASTE57( \
2840 func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, \
2841 v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2842 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) \
2843 NLOHMANN_JSON_PASTE2(func, v1) \
2844 NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2845 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2846 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2847 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2848#define NLOHMANN_JSON_PASTE58( \
2849 func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, \
2850 v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, \
2851 v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) \
2852 NLOHMANN_JSON_PASTE2(func, v1) \
2853 NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2854 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2855 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2856 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2857#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2858 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2859 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2860 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2861 v54, v55, v56, v57, v58) \
2862 NLOHMANN_JSON_PASTE2(func, v1) \
2863 NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2864 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2865 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2866 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2867#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2868 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2869 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2870 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2871 v54, v55, v56, v57, v58, v59) \
2872 NLOHMANN_JSON_PASTE2(func, v1) \
2873 NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2874 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2875 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2876 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, \
2877 v59)
2878#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2879 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2880 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2881 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2882 v54, v55, v56, v57, v58, v59, v60) \
2883 NLOHMANN_JSON_PASTE2(func, v1) \
2884 NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2885 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2886 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2887 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, \
2888 v59, v60)
2889#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2890 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2891 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2892 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2893 v54, v55, v56, v57, v58, v59, v60, v61) \
2894 NLOHMANN_JSON_PASTE2(func, v1) \
2895 NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2896 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2897 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2898 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, \
2899 v59, v60, v61)
2900#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2901 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2902 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2903 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2904 v54, v55, v56, v57, v58, v59, v60, v61, v62) \
2905 NLOHMANN_JSON_PASTE2(func, v1) \
2906 NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2907 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2908 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2909 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, \
2910 v59, v60, v61, v62)
2911#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, \
2912 v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, \
2913 v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, \
2914 v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, \
2915 v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) \
2916 NLOHMANN_JSON_PASTE2(func, v1) \
2917 NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, \
2918 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
2919 v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, \
2920 v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, \
2921 v59, v60, v61, v62, v63)
2922
2923#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2924#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2925#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) \
2926 nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2927
2933#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2934 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2935 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2936 } \
2937 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { \
2938 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
2939 }
2940
2941#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2942 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2943 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2944 } \
2945 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { \
2946 const Type nlohmann_json_default_obj{}; \
2947 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) \
2948 }
2949
2950#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2951 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2952 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2953 }
2954
2960#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2961 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2962 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2963 } \
2964 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { \
2965 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) \
2966 }
2967
2968#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2969 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2970 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2971 }
2972
2973#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2974 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { \
2975 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) \
2976 } \
2977 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { \
2978 const Type nlohmann_json_default_obj{}; \
2979 NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) \
2980 }
2981
2982// inspired from https://stackoverflow.com/a/26745591
2983// allows to call any std function as if (e.g. with begin):
2984// using std::begin; begin(x);
2985//
2986// it allows using the detected idiom to retrieve the return type
2987// of such an expression
2988#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2989 namespace detail { \
2990 using std::std_name; \
2991 \
2992 template <typename... T> \
2993 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2994 } \
2995 \
2996 namespace detail2 { \
2997 struct std_name##_tag {}; \
2998 \
2999 template <typename... T> std_name##_tag std_name(T&&...); \
3000 \
3001 template <typename... T> \
3002 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
3003 \
3004 template <typename... T> struct would_call_std_##std_name { \
3005 static constexpr auto const value = \
3006 ::nlohmann::detail::is_detected_exact<std_name##_tag, result_of_##std_name, \
3007 T...>::value; \
3008 }; \
3009 } /* namespace detail2 */ \
3010 \
3011 template <typename... T> \
3012 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> {}
3013
3014#ifndef JSON_USE_IMPLICIT_CONVERSIONS
3015#define JSON_USE_IMPLICIT_CONVERSIONS 1
3016#endif
3017
3018#if JSON_USE_IMPLICIT_CONVERSIONS
3019#define JSON_EXPLICIT
3020#else
3021#define JSON_EXPLICIT explicit
3022#endif
3023
3024#ifndef JSON_DISABLE_ENUM_SERIALIZATION
3025#define JSON_DISABLE_ENUM_SERIALIZATION 0
3026#endif
3027
3028#ifndef JSON_USE_GLOBAL_UDLS
3029#define JSON_USE_GLOBAL_UDLS 1
3030#endif
3031
3032#if JSON_HAS_THREE_WAY_COMPARISON
3033#include <compare> // partial_ordering
3034#endif
3035
3036NLOHMANN_JSON_NAMESPACE_BEGIN
3037namespace detail {
3038
3040// JSON type enumeration //
3042
3079
3093#if JSON_HAS_THREE_WAY_COMPARISON
3094inline std::partial_ordering operator<=>(const value_t lhs,
3095 const value_t rhs) noexcept // *NOPAD*
3096#else
3097inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3098#endif
3099{
3100 static constexpr std::array<std::uint8_t, 9> order = {{
3101 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 1 /* boolean */,
3102 2 /* integer */, 2 /* unsigned */, 2 /* float */, 6 /* binary */
3103 }};
3104
3105 const auto l_index = static_cast<std::size_t>(lhs);
3106 const auto r_index = static_cast<std::size_t>(rhs);
3107#if JSON_HAS_THREE_WAY_COMPARISON
3108 if (l_index < order.size() && r_index < order.size()) {
3109 return order[l_index] <=> order[r_index]; // *NOPAD*
3110 }
3111 return std::partial_ordering::unordered;
3112#else
3113 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3114#endif
3115}
3116
3117// GCC selects the built-in operator< over an operator rewritten from
3118// a user-defined spaceship operator
3119// Clang, MSVC, and ICC select the rewritten candidate
3120// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3121#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3122inline bool operator<(const value_t lhs, const value_t rhs) noexcept {
3123 return std::is_lt(lhs <=> rhs); // *NOPAD*
3124}
3125#endif
3126
3127} // namespace detail
3128NLOHMANN_JSON_NAMESPACE_END
3129
3130// #include <nlohmann/detail/string_escape.hpp>
3131// __ _____ _____ _____
3132// __| | __| | | | JSON for Modern C++
3133// | | |__ | | | | | | version 3.11.3
3134// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3135//
3136// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3137// SPDX-License-Identifier: MIT
3138
3139// #include <nlohmann/detail/abi_macros.hpp>
3140
3141NLOHMANN_JSON_NAMESPACE_BEGIN
3142namespace detail {
3143
3157template <typename StringType>
3158inline void replace_substring(StringType& s, const StringType& f, const StringType& t) {
3159 JSON_ASSERT(!f.empty());
3160 for (auto pos = s.find(f); // find first occurrence of f
3161 pos != StringType::npos; // make sure f was found
3162 s.replace(pos, f.size(), t), // replace with t, and
3163 pos = s.find(f, pos + t.size())) // find next occurrence of f
3164 {
3165 }
3166}
3167
3175template <typename StringType> inline StringType escape(StringType s) {
3176 replace_substring(s, StringType{"~"}, StringType{"~0"});
3177 replace_substring(s, StringType{"/"}, StringType{"~1"});
3178 return s;
3179}
3180
3188template <typename StringType> static void unescape(StringType& s) {
3189 replace_substring(s, StringType{"~1"}, StringType{"/"});
3190 replace_substring(s, StringType{"~0"}, StringType{"~"});
3191}
3192
3193} // namespace detail
3194NLOHMANN_JSON_NAMESPACE_END
3195
3196// #include <nlohmann/detail/input/position_t.hpp>
3197// __ _____ _____ _____
3198// __| | __| | | | JSON for Modern C++
3199// | | |__ | | | | | | version 3.11.3
3200// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3201//
3202// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3203// SPDX-License-Identifier: MIT
3204
3205#include <cstddef> // size_t
3206
3207// #include <nlohmann/detail/abi_macros.hpp>
3208
3209NLOHMANN_JSON_NAMESPACE_BEGIN
3210namespace detail {
3211
3215 std::size_t chars_read_total = 0;
3219 std::size_t lines_read = 0;
3220
3222 constexpr operator size_t() const { return chars_read_total; }
3223};
3224
3225} // namespace detail
3226NLOHMANN_JSON_NAMESPACE_END
3227
3228// #include <nlohmann/detail/macro_scope.hpp>
3229
3230// #include <nlohmann/detail/meta/cpp_future.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-FileCopyrightText: 2018 The Abseil Authors
3238// SPDX-License-Identifier: MIT
3239
3240#include <array> // array
3241#include <cstddef> // size_t
3242#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3243#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3244
3245// #include <nlohmann/detail/macro_scope.hpp>
3246
3247NLOHMANN_JSON_NAMESPACE_BEGIN
3248namespace detail {
3249
3250template <typename T>
3251using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3252
3253#ifdef JSON_HAS_CPP_14
3254
3255// the following utilities are natively available in C++14
3256using std::enable_if_t;
3257using std::index_sequence;
3258using std::index_sequence_for;
3259using std::make_index_sequence;
3260
3261#else
3262
3263// alias templates to reduce boilerplate
3264template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type;
3265
3266// The following code is taken from
3267// https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3268// which is part of Google Abseil (https://github.com/abseil/abseil-cpp),
3269// licensed under the Apache License 2.0.
3270
3272
3273// integer_sequence
3274//
3275// Class template representing a compile-time integer sequence. An instantiation
3276// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3277// type through its template arguments (which is a common need when
3278// working with C++11 variadic templates). `absl::integer_sequence` is designed
3279// to be a drop-in replacement for C++14's `std::integer_sequence`.
3280//
3281// Example:
3282//
3283// template< class T, T... Ints >
3284// void user_function(integer_sequence<T, Ints...>);
3285//
3286// int main()
3287// {
3288// // user_function's `T` will be deduced to `int` and `Ints...`
3289// // will be deduced to `0, 1, 2, 3, 4`.
3290// user_function(make_integer_sequence<int, 5>());
3291// }
3292template <typename T, T... Ints> struct integer_sequence {
3293 using value_type = T;
3294 static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
3295};
3296
3297// index_sequence
3298//
3299// A helper template for an `integer_sequence` of `size_t`,
3300// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3301// `std::index_sequence`.
3302template <size_t... Ints> using index_sequence = integer_sequence<size_t, Ints...>;
3303
3304namespace utility_internal {
3305
3306template <typename Seq, size_t SeqSize, size_t Rem> struct Extend;
3307
3308// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3309template <typename T, T... Ints, size_t SeqSize>
3310struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> {
3311 using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
3312};
3313
3314template <typename T, T... Ints, size_t SeqSize>
3315struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> {
3316 using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
3317};
3318
3319// Recursion helper for 'make_integer_sequence<T, N>'.
3320// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3321template <typename T, size_t N> struct Gen {
3322 using type = typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
3323};
3324
3325template <typename T> struct Gen<T, 0> {
3326 using type = integer_sequence<T>;
3327};
3328
3329} // namespace utility_internal
3330
3331// Compile-time sequences of integers
3332
3333// make_integer_sequence
3334//
3335// This template alias is equivalent to
3336// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3337// replacement for C++14's `std::make_integer_sequence`.
3338template <typename T, T N> using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3339
3340// make_index_sequence
3341//
3342// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3343// and is designed to be a drop-in replacement for C++14's
3344// `std::make_index_sequence`.
3345template <size_t N> using make_index_sequence = make_integer_sequence<size_t, N>;
3346
3347// index_sequence_for
3348//
3349// Converts a typename pack into an index sequence of the same length, and
3350// is designed to be a drop-in replacement for C++14's
3351// `std::index_sequence_for()`
3352template <typename... Ts> using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3353
3355
3356#endif
3357
3358// dispatch utility (taken from ranges-v3)
3359template <unsigned N> struct priority_tag : priority_tag<N - 1> {};
3360template <> struct priority_tag<0> {};
3361
3362// taken from ranges-v3
3363template <typename T> struct static_const {
3364 static JSON_INLINE_VARIABLE constexpr T value{};
3365};
3366
3367#ifndef JSON_HAS_CPP_17
3368template <typename T> constexpr T static_const<T>::value;
3369#endif
3370
3371template <typename T, typename... Args>
3372inline constexpr std::array<T, sizeof...(Args)> make_array(Args&&... args) {
3373 return std::array<T, sizeof...(Args)>{{static_cast<T>(std::forward<Args>(args))...}};
3374}
3375
3376} // namespace detail
3377NLOHMANN_JSON_NAMESPACE_END
3378
3379// #include <nlohmann/detail/meta/type_traits.hpp>
3380// __ _____ _____ _____
3381// __| | __| | | | JSON for Modern C++
3382// | | |__ | | | | | | version 3.11.3
3383// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3384//
3385// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3386// SPDX-License-Identifier: MIT
3387
3388#include <limits> // numeric_limits
3389#include <string> // char_traits
3390#include <tuple> // tuple
3391#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3392#include <utility> // declval
3393
3394// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3395// __ _____ _____ _____
3396// __| | __| | | | JSON for Modern C++
3397// | | |__ | | | | | | version 3.11.3
3398// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3399//
3400// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3401// SPDX-License-Identifier: MIT
3402
3403#include <iterator> // random_access_iterator_tag
3404
3405// #include <nlohmann/detail/abi_macros.hpp>
3406
3407// #include <nlohmann/detail/meta/void_t.hpp>
3408
3409// #include <nlohmann/detail/meta/cpp_future.hpp>
3410
3411NLOHMANN_JSON_NAMESPACE_BEGIN
3412namespace detail {
3413
3414template <typename It, typename = void> struct iterator_types {};
3415
3416template <typename It>
3418 It, void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3419 typename It::reference, typename It::iterator_category>> {
3420 using difference_type = typename It::difference_type;
3421 using value_type = typename It::value_type;
3422 using pointer = typename It::pointer;
3423 using reference = typename It::reference;
3424 using iterator_category = typename It::iterator_category;
3425};
3426
3427// This is required as some compilers implement std::iterator_traits in a way
3428// that doesn't work with SFINAE. See
3429// https://github.com/nlohmann/json/issues/1341.
3430template <typename T, typename = void> struct iterator_traits {};
3431
3432template <typename T>
3433struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>> : iterator_types<T> {};
3434
3435template <typename T> struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
3436 using iterator_category = std::random_access_iterator_tag;
3437 using value_type = T;
3438 using difference_type = ptrdiff_t;
3439 using pointer = T*;
3440 using reference = T&;
3441};
3442
3443} // namespace detail
3444NLOHMANN_JSON_NAMESPACE_END
3445
3446// #include <nlohmann/detail/macro_scope.hpp>
3447
3448// #include <nlohmann/detail/meta/call_std/begin.hpp>
3449// __ _____ _____ _____
3450// __| | __| | | | JSON for Modern C++
3451// | | |__ | | | | | | version 3.11.3
3452// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3453//
3454// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3455// SPDX-License-Identifier: MIT
3456
3457// #include <nlohmann/detail/macro_scope.hpp>
3458
3459NLOHMANN_JSON_NAMESPACE_BEGIN
3460
3461NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3462
3463NLOHMANN_JSON_NAMESPACE_END
3464
3465// #include <nlohmann/detail/meta/call_std/end.hpp>
3466// __ _____ _____ _____
3467// __| | __| | | | JSON for Modern C++
3468// | | |__ | | | | | | version 3.11.3
3469// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3470//
3471// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3472// SPDX-License-Identifier: MIT
3473
3474// #include <nlohmann/detail/macro_scope.hpp>
3475
3476NLOHMANN_JSON_NAMESPACE_BEGIN
3477
3478NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3479
3480NLOHMANN_JSON_NAMESPACE_END
3481
3482// #include <nlohmann/detail/meta/cpp_future.hpp>
3483
3484// #include <nlohmann/detail/meta/detected.hpp>
3485
3486// #include <nlohmann/json_fwd.hpp>
3487// __ _____ _____ _____
3488// __| | __| | | | JSON for Modern C++
3489// | | |__ | | | | | | version 3.11.3
3490// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3491//
3492// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3493// SPDX-License-Identifier: MIT
3494
3495#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3496#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3497
3498#include <cstdint> // int64_t, uint64_t
3499#include <map> // map
3500#include <memory> // allocator
3501#include <string> // string
3502#include <vector> // vector
3503
3504// #include <nlohmann/detail/abi_macros.hpp>
3505
3511NLOHMANN_JSON_NAMESPACE_BEGIN
3512
3520template <typename T = void, typename SFINAE = void> struct adl_serializer;
3521
3524template <template <typename U, typename V, typename... Args> class ObjectType = std::map,
3525 template <typename U, typename... Args> class ArrayType = std::vector,
3526 class StringType = std::string, class BooleanType = bool,
3527 class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t,
3528 class NumberFloatType = double,
3529 template <typename U> class AllocatorType = std::allocator,
3530 template <typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
3531 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3532 class CustomBaseClass = void>
3533class basic_json;
3534
3538template <typename RefStringType> class json_pointer;
3539
3544using json = basic_json<>;
3545
3548template <class Key, class T, class IgnoredLess, class Allocator> struct ordered_map;
3549
3552using ordered_json = basic_json<nlohmann::ordered_map>;
3553
3554NLOHMANN_JSON_NAMESPACE_END
3555
3556#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3557
3558NLOHMANN_JSON_NAMESPACE_BEGIN
3567namespace detail {
3568
3570// helpers //
3572
3573// Note to maintainers:
3574//
3575// Every trait in this file expects a non CV-qualified type.
3576// The only exceptions are in the 'aliases for detected' section
3577// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3578//
3579// In this case, T has to be properly CV-qualified to constraint the function
3580// arguments (e.g. to_json(BasicJsonType&, const T&))
3581
3582template <typename> struct is_basic_json : std::false_type {};
3583
3584NLOHMANN_BASIC_JSON_TPL_DECLARATION
3585struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3586
3587// used by exceptions create() member functions
3588// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3589// false_type otherwise
3590template <typename BasicJsonContext>
3592 : std::integral_constant<
3593 bool, is_basic_json<typename std::remove_cv<
3594 typename std::remove_pointer<BasicJsonContext>::type>::type>::value ||
3595 std::is_same<BasicJsonContext, std::nullptr_t>::value> {};
3596
3598// json_ref helpers //
3600
3601template <typename> class json_ref;
3602
3603template <typename> struct is_json_ref : std::false_type {};
3604
3605template <typename T> struct is_json_ref<json_ref<T>> : std::true_type {};
3606
3608// aliases for detected //
3610
3611template <typename T> using mapped_type_t = typename T::mapped_type;
3612
3613template <typename T> using key_type_t = typename T::key_type;
3614
3615template <typename T> using value_type_t = typename T::value_type;
3616
3617template <typename T> using difference_type_t = typename T::difference_type;
3618
3619template <typename T> using pointer_t = typename T::pointer;
3620
3621template <typename T> using reference_t = typename T::reference;
3622
3623template <typename T> using iterator_category_t = typename T::iterator_category;
3624
3625template <typename T, typename... Args>
3626using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3627
3628template <typename T, typename... Args>
3629using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3630
3631template <typename T, typename U>
3632using get_template_function = decltype(std::declval<T>().template get<U>());
3633
3634// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3635template <typename BasicJsonType, typename T, typename = void>
3636struct has_from_json : std::false_type {};
3637
3638// trait checking if j.get<T> is valid
3639// use this trait instead of std::is_constructible or std::is_convertible,
3640// both rely on, or make use of implicit conversions, and thus fail when T
3641// has several constructors/operator= (see
3642// https://github.com/nlohmann/json/issues/958)
3643template <typename BasicJsonType, typename T> struct is_getable {
3644 static constexpr bool value =
3645 is_detected<get_template_function, const BasicJsonType&, T>::value;
3646};
3647
3648template <typename BasicJsonType, typename T>
3649struct has_from_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>> {
3650 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3651
3652 static constexpr bool value =
3653 is_detected_exact<void, from_json_function, serializer, const BasicJsonType&, T&>::value;
3654};
3655
3656// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3657// this overload is used for non-default-constructible user-defined-types
3658template <typename BasicJsonType, typename T, typename = void>
3659struct has_non_default_from_json : std::false_type {};
3660
3661template <typename BasicJsonType, typename T>
3662struct has_non_default_from_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>> {
3663 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3664
3665 static constexpr bool value =
3666 is_detected_exact<T, from_json_function, serializer, const BasicJsonType&>::value;
3667};
3668
3669// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3670// Do not evaluate the trait when T is a basic_json type, to avoid template
3671// instantiation infinite recursion.
3672template <typename BasicJsonType, typename T, typename = void>
3673struct has_to_json : std::false_type {};
3674
3675template <typename BasicJsonType, typename T>
3676struct has_to_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>> {
3677 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3678
3679 static constexpr bool value =
3680 is_detected_exact<void, to_json_function, serializer, BasicJsonType&, T>::value;
3681};
3682
3683template <typename T> using detect_key_compare = typename T::key_compare;
3684
3685template <typename T>
3686struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3687
3688// obtains the actual object key comparator
3689template <typename BasicJsonType> struct actual_object_comparator {
3690 using object_t = typename BasicJsonType::object_t;
3691 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3692 using type =
3693 typename std::conditional<has_key_compare<object_t>::value, typename object_t::key_compare,
3694 object_comparator_t>::type;
3695};
3696
3697template <typename BasicJsonType>
3698using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3699
3701// char_traits //
3703
3704// Primary template of char_traits calls std char_traits
3705template <typename T> struct char_traits : std::char_traits<T> {};
3706
3707// Explicitly define char traits for unsigned char since it is not standard
3708template <> struct char_traits<unsigned char> : std::char_traits<char> {
3709 using char_type = unsigned char;
3710 using int_type = uint64_t;
3711
3712 // Redefine to_int_type function
3713 static int_type to_int_type(char_type c) noexcept { return static_cast<int_type>(c); }
3714
3715 static char_type to_char_type(int_type i) noexcept { return static_cast<char_type>(i); }
3716
3717 static constexpr int_type eof() noexcept { return static_cast<int_type>(EOF); }
3718};
3719
3720// Explicitly define char traits for signed char since it is not standard
3721template <> struct char_traits<signed char> : std::char_traits<char> {
3722 using char_type = signed char;
3723 using int_type = uint64_t;
3724
3725 // Redefine to_int_type function
3726 static int_type to_int_type(char_type c) noexcept { return static_cast<int_type>(c); }
3727
3728 static char_type to_char_type(int_type i) noexcept { return static_cast<char_type>(i); }
3729
3730 static constexpr int_type eof() noexcept { return static_cast<int_type>(EOF); }
3731};
3732
3734// is_ functions //
3736
3737// https://en.cppreference.com/w/cpp/types/conjunction
3738template <class...> struct conjunction : std::true_type {};
3739template <class B> struct conjunction<B> : B {};
3740template <class B, class... Bn>
3741struct conjunction<B, Bn...>
3742 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3743
3744// https://en.cppreference.com/w/cpp/types/negation
3745template <class B> struct negation : std::integral_constant<bool, !B::value> {};
3746
3747// Reimplementation of is_constructible and is_default_constructible, due to
3748// them being broken for std::pair and std::tuple until LWG 2367 fix (see
3749// https://cplusplus.github.io/LWG/lwg-defects.html#2367). This causes compile
3750// errors in e.g. clang 3.5 or gcc 4.9.
3751template <typename T> struct is_default_constructible : std::is_default_constructible<T> {};
3752
3753template <typename T1, typename T2>
3754struct is_default_constructible<std::pair<T1, T2>>
3755 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3756
3757template <typename T1, typename T2>
3758struct is_default_constructible<const std::pair<T1, T2>>
3759 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3760
3761template <typename... Ts>
3762struct is_default_constructible<std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...> {
3763};
3764
3765template <typename... Ts>
3766struct is_default_constructible<const std::tuple<Ts...>>
3767 : conjunction<is_default_constructible<Ts>...> {};
3768
3769template <typename T, typename... Args>
3770struct is_constructible : std::is_constructible<T, Args...> {};
3771
3772template <typename T1, typename T2>
3773struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3774
3775template <typename T1, typename T2>
3776struct is_constructible<const std::pair<T1, T2>>
3777 : is_default_constructible<const std::pair<T1, T2>> {};
3778
3779template <typename... Ts>
3780struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3781
3782template <typename... Ts>
3783struct is_constructible<const std::tuple<Ts...>>
3784 : is_default_constructible<const std::tuple<Ts...>> {};
3785
3786template <typename T, typename = void> struct is_iterator_traits : std::false_type {};
3787
3788template <typename T> struct is_iterator_traits<iterator_traits<T>> {
3789 private:
3790 using traits = iterator_traits<T>;
3791
3792 public:
3793 static constexpr auto value =
3794 is_detected<value_type_t, traits>::value && is_detected<difference_type_t, traits>::value &&
3795 is_detected<pointer_t, traits>::value && is_detected<iterator_category_t, traits>::value &&
3796 is_detected<reference_t, traits>::value;
3797};
3798
3799template <typename T> struct is_range {
3800 private:
3801 using t_ref = typename std::add_lvalue_reference<T>::type;
3802
3803 using iterator = detected_t<result_of_begin, t_ref>;
3804 using sentinel = detected_t<result_of_end, t_ref>;
3805
3806 // to be 100% correct, it should use
3807 // https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator and
3808 // https://en.cppreference.com/w/cpp/iterator/sentinel_for but reimplementing
3809 // these would be too much work, as a lot of other concepts are used
3810 // underneath
3811 static constexpr auto is_iterator_begin = is_iterator_traits<iterator_traits<iterator>>::value;
3812
3813 public:
3814 static constexpr bool value = !std::is_same<iterator, nonesuch>::value &&
3815 !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3816};
3817
3818template <typename R>
3819using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3820
3821template <typename T> using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3822
3823// The following implementation of is_complete_type is taken from
3824// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3825// and is written by Xiang Fan who agreed to using it in this library.
3826
3827template <typename T, typename = void> struct is_complete_type : std::false_type {};
3828
3829template <typename T> struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3830
3831template <typename BasicJsonType, typename CompatibleObjectType, typename = void>
3832struct is_compatible_object_type_impl : std::false_type {};
3833
3834template <typename BasicJsonType, typename CompatibleObjectType>
3836 BasicJsonType, CompatibleObjectType,
3837 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value &&
3838 is_detected<key_type_t, CompatibleObjectType>::value>> {
3839 using object_t = typename BasicJsonType::object_t;
3840
3841 // macOS's is_constructible does not play well with nonesuch...
3842 static constexpr bool value =
3843 is_constructible<typename object_t::key_type,
3844 typename CompatibleObjectType::key_type>::value &&
3845 is_constructible<typename object_t::mapped_type,
3846 typename CompatibleObjectType::mapped_type>::value;
3847};
3848
3849template <typename BasicJsonType, typename CompatibleObjectType>
3851 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3852
3853template <typename BasicJsonType, typename ConstructibleObjectType, typename = void>
3854struct is_constructible_object_type_impl : std::false_type {};
3855
3856template <typename BasicJsonType, typename ConstructibleObjectType>
3858 BasicJsonType, ConstructibleObjectType,
3859 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value &&
3860 is_detected<key_type_t, ConstructibleObjectType>::value>> {
3861 using object_t = typename BasicJsonType::object_t;
3862
3863 static constexpr bool value =
3865 (std::is_move_assignable<ConstructibleObjectType>::value ||
3866 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3867 (is_constructible<typename ConstructibleObjectType::key_type,
3868 typename object_t::key_type>::value &&
3869 std::is_same<typename object_t::mapped_type,
3870 typename ConstructibleObjectType::mapped_type>::value)) ||
3872 has_non_default_from_json<BasicJsonType,
3873 typename ConstructibleObjectType::mapped_type>::value);
3874};
3875
3876template <typename BasicJsonType, typename ConstructibleObjectType>
3878 : is_constructible_object_type_impl<BasicJsonType, ConstructibleObjectType> {};
3879
3880template <typename BasicJsonType, typename CompatibleStringType> struct is_compatible_string_type {
3881 static constexpr auto value =
3883};
3884
3885template <typename BasicJsonType, typename ConstructibleStringType>
3887 // launder type through decltype() to fix compilation failure on ICPC
3888#ifdef __INTEL_COMPILER
3889 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3890#else
3891 using laundered_type = ConstructibleStringType;
3892#endif
3893
3894 static constexpr auto value =
3896 is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t,
3897 laundered_type>>::value;
3898};
3899
3900template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
3901struct is_compatible_array_type_impl : std::false_type {};
3902
3903template <typename BasicJsonType, typename CompatibleArrayType>
3905 BasicJsonType, CompatibleArrayType,
3906 enable_if_t<
3907 is_detected<iterator_t, CompatibleArrayType>::value &&
3908 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
3909 // special case for types like std::filesystem::path whose iterator's
3910 // value_type are themselves c.f.
3911 // https://github.com/nlohmann/json/pull/3073
3912 !std::is_same<CompatibleArrayType,
3913 detected_t<range_value_t, CompatibleArrayType>>::value>> {
3914 static constexpr bool value =
3916};
3917
3918template <typename BasicJsonType, typename CompatibleArrayType>
3920 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3921
3922template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3923struct is_constructible_array_type_impl : std::false_type {};
3924
3925template <typename BasicJsonType, typename ConstructibleArrayType>
3927 BasicJsonType, ConstructibleArrayType,
3928 enable_if_t<std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value>>
3929 : std::true_type {};
3930
3931template <typename BasicJsonType, typename ConstructibleArrayType>
3933 BasicJsonType, ConstructibleArrayType,
3934 enable_if_t<!std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value &&
3935 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value &&
3936 is_default_constructible<ConstructibleArrayType>::value &&
3937 (std::is_move_assignable<ConstructibleArrayType>::value ||
3938 std::is_copy_assignable<ConstructibleArrayType>::value) &&
3939 is_detected<iterator_t, ConstructibleArrayType>::value &&
3941 iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value &&
3942 is_detected<range_value_t, ConstructibleArrayType>::value &&
3943 // special case for types like std::filesystem::path whose
3944 // iterator's value_type are themselves c.f.
3945 // https://github.com/nlohmann/json/pull/3073
3946 !std::is_same<ConstructibleArrayType,
3947 detected_t<range_value_t, ConstructibleArrayType>>::value &&
3948 is_complete_type<detected_t<range_value_t, ConstructibleArrayType>>::value>> {
3949 using value_type = range_value_t<ConstructibleArrayType>;
3950
3951 static constexpr bool value =
3952 std::is_same<value_type, typename BasicJsonType::array_t::value_type>::value ||
3955};
3956
3957template <typename BasicJsonType, typename ConstructibleArrayType>
3959 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3960
3961template <typename RealIntegerType, typename CompatibleNumberIntegerType, typename = void>
3962struct is_compatible_integer_type_impl : std::false_type {};
3963
3964template <typename RealIntegerType, typename CompatibleNumberIntegerType>
3966 RealIntegerType, CompatibleNumberIntegerType,
3967 enable_if_t<std::is_integral<RealIntegerType>::value &&
3968 std::is_integral<CompatibleNumberIntegerType>::value &&
3969 !std::is_same<bool, CompatibleNumberIntegerType>::value>> {
3970 // is there an assert somewhere on overflows?
3971 using RealLimits = std::numeric_limits<RealIntegerType>;
3972 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3973
3974 static constexpr auto value =
3976 CompatibleLimits::is_integer && RealLimits::is_signed == CompatibleLimits::is_signed;
3977};
3978
3979template <typename RealIntegerType, typename CompatibleNumberIntegerType>
3981 : is_compatible_integer_type_impl<RealIntegerType, CompatibleNumberIntegerType> {};
3982
3983template <typename BasicJsonType, typename CompatibleType, typename = void>
3984struct is_compatible_type_impl : std::false_type {};
3985
3986template <typename BasicJsonType, typename CompatibleType>
3987struct is_compatible_type_impl<BasicJsonType, CompatibleType,
3988 enable_if_t<is_complete_type<CompatibleType>::value>> {
3989 static constexpr bool value = has_to_json<BasicJsonType, CompatibleType>::value;
3990};
3991
3992template <typename BasicJsonType, typename CompatibleType>
3993struct is_compatible_type : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3994
3995template <typename T1, typename T2> struct is_constructible_tuple : std::false_type {};
3996
3997template <typename T1, typename... Args>
3998struct is_constructible_tuple<T1, std::tuple<Args...>>
3999 : conjunction<is_constructible<T1, Args>...> {};
4000
4001template <typename BasicJsonType, typename T> struct is_json_iterator_of : std::false_type {};
4002
4003template <typename BasicJsonType>
4004struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4005
4006template <typename BasicJsonType>
4007struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type {
4008};
4009
4010// checks if a given type T is a template specialization of Primary
4011template <template <typename...> class Primary, typename T>
4012struct is_specialization_of : std::false_type {};
4013
4014template <template <typename...> class Primary, typename... Args>
4015struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4016
4017template <typename T>
4019
4020// checks if A and B are comparable using Compare functor
4021template <typename Compare, typename A, typename B, typename = void>
4022struct is_comparable : std::false_type {};
4023
4024template <typename Compare, typename A, typename B>
4026 Compare, A, B,
4027 void_t<decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4028 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>>
4029 : std::true_type {};
4030
4031template <typename T> using detect_is_transparent = typename T::is_transparent;
4032
4033// type trait to check if KeyType can be used as object key (without a
4034// BasicJsonType) see is_usable_as_basic_json_key_type below
4035template <typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef,
4036 bool RequireTransparentComparator = true,
4037 bool ExcludeObjectKeyType = RequireTransparentComparator,
4038 typename KeyType = uncvref_t<KeyTypeCVRef>>
4039using is_usable_as_key_type = typename std::conditional<
4041 !(ExcludeObjectKeyType && std::is_same<KeyType, ObjectKeyType>::value) &&
4042 (!RequireTransparentComparator || is_detected<detect_is_transparent, Comparator>::value) &&
4043 !is_json_pointer<KeyType>::value,
4044 std::true_type, std::false_type>::type;
4045
4046// type trait to check if KeyType can be used as object key
4047// true if:
4048// - KeyType is comparable with BasicJsonType::object_t::key_type
4049// - if ExcludeObjectKeyType is true, KeyType is not
4050// BasicJsonType::object_t::key_type
4051// - the comparator is transparent or RequireTransparentComparator is false
4052// - KeyType is not a JSON iterator or json_pointer
4053template <typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4054 bool ExcludeObjectKeyType = RequireTransparentComparator,
4055 typename KeyType = uncvref_t<KeyTypeCVRef>>
4056using is_usable_as_basic_json_key_type = typename std::conditional<
4057 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4058 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4059 RequireTransparentComparator, ExcludeObjectKeyType>::value &&
4061 std::true_type, std::false_type>::type;
4062
4063template <typename ObjectType, typename KeyType>
4064using detect_erase_with_key_type =
4065 decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4066
4067// type trait to check if object_t has an erase() member functions accepting
4068// KeyType
4069template <typename BasicJsonType, typename KeyType>
4070using has_erase_with_key_type = typename std::conditional<
4071 is_detected<detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType>::value,
4072 std::true_type, std::false_type>::type;
4073
4074// a naive helper to check if a type is an ordered_map (exploits the fact that
4075// ordered_map inherits capacity() from std::vector)
4076template <typename T> struct is_ordered_map {
4077 using one = char;
4078
4079 struct two {
4080 char x
4081 [2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4082 };
4083
4084 template <typename C> static one test(decltype(&C::capacity));
4085 template <typename C> static two test(...);
4086
4087 enum {
4088 value = sizeof(test<T>(nullptr)) == sizeof(char)
4089 }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4090};
4091
4092// to avoid useless casts (see
4093// https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4094template <typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0>
4095T conditional_static_cast(U value) {
4096 return static_cast<T>(value);
4097}
4098
4099template <typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4100T conditional_static_cast(U value) {
4101 return value;
4102}
4103
4104template <typename... Types> using all_integral = conjunction<std::is_integral<Types>...>;
4105
4106template <typename... Types> using all_signed = conjunction<std::is_signed<Types>...>;
4107
4108template <typename... Types> using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4109
4110// there's a disjunction trait in another PR; replace when merged
4111template <typename... Types>
4112using same_sign =
4113 std::integral_constant<bool, all_signed<Types...>::value || all_unsigned<Types...>::value>;
4114
4115template <typename OfType, typename T>
4116using never_out_of_range =
4117 std::integral_constant<bool, (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) ||
4118 (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T))>;
4119
4120template <typename OfType, typename T, bool OfTypeSigned = std::is_signed<OfType>::value,
4121 bool TSigned = std::is_signed<T>::value>
4123
4124template <typename OfType, typename T> struct value_in_range_of_impl2<OfType, T, false, false> {
4125 static constexpr bool test(T val) {
4126 using CommonType = typename std::common_type<OfType, T>::type;
4127 return static_cast<CommonType>(val) <=
4128 static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4129 }
4130};
4131
4132template <typename OfType, typename T> struct value_in_range_of_impl2<OfType, T, true, false> {
4133 static constexpr bool test(T val) {
4134 using CommonType = typename std::common_type<OfType, T>::type;
4135 return static_cast<CommonType>(val) <=
4136 static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4137 }
4138};
4139
4140template <typename OfType, typename T> struct value_in_range_of_impl2<OfType, T, false, true> {
4141 static constexpr bool test(T val) {
4142 using CommonType = typename std::common_type<OfType, T>::type;
4143 return val >= 0 && static_cast<CommonType>(val) <=
4144 static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4145 }
4146};
4147
4148template <typename OfType, typename T> struct value_in_range_of_impl2<OfType, T, true, true> {
4149 static constexpr bool test(T val) {
4150 using CommonType = typename std::common_type<OfType, T>::type;
4151 return static_cast<CommonType>(val) >=
4152 static_cast<CommonType>((std::numeric_limits<OfType>::min)()) &&
4153 static_cast<CommonType>(val) <=
4154 static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4155 }
4156};
4157
4158template <typename OfType, typename T, bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4159 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4161
4162template <typename OfType, typename T> struct value_in_range_of_impl1<OfType, T, false> {
4163 static constexpr bool test(T val) { return value_in_range_of_impl2<OfType, T>::test(val); }
4164};
4165
4166template <typename OfType, typename T> struct value_in_range_of_impl1<OfType, T, true> {
4167 static constexpr bool test(T /*val*/) { return true; }
4168};
4169
4170template <typename OfType, typename T> inline constexpr bool value_in_range_of(T val) {
4172}
4173
4174template <bool Value> using bool_constant = std::integral_constant<bool, Value>;
4175
4177// is_c_string
4179
4180namespace impl {
4181
4182template <typename T> inline constexpr bool is_c_string() {
4183 using TUnExt = typename std::remove_extent<T>::type;
4184 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4185 using TUnPtr = typename std::remove_pointer<T>::type;
4186 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4187 return (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) ||
4188 (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4189}
4190
4191} // namespace impl
4192
4193// checks whether T is a [cv] char */[cv] char[] C string
4194template <typename T> struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4195
4196template <typename T> using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4197
4199// is_transparent
4201
4202namespace impl {
4203
4204template <typename T> inline constexpr bool is_transparent() {
4205 return is_detected<detect_is_transparent, T>::value;
4206}
4207
4208} // namespace impl
4209
4210// checks whether T has a member named is_transparent
4211template <typename T> struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4212
4214
4215} // namespace detail
4216NLOHMANN_JSON_NAMESPACE_END
4217
4218// #include <nlohmann/detail/string_concat.hpp>
4219// __ _____ _____ _____
4220// __| | __| | | | JSON for Modern C++
4221// | | |__ | | | | | | version 3.11.3
4222// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4223//
4224// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4225// SPDX-License-Identifier: MIT
4226
4227#include <cstring> // strlen
4228#include <string> // string
4229#include <utility> // forward
4230
4231// #include <nlohmann/detail/meta/cpp_future.hpp>
4232
4233// #include <nlohmann/detail/meta/detected.hpp>
4234
4235NLOHMANN_JSON_NAMESPACE_BEGIN
4236namespace detail {
4237
4238inline std::size_t concat_length() {
4239 return 0;
4240}
4241
4242template <typename... Args> inline std::size_t concat_length(const char* cstr, const Args&... rest);
4243
4244template <typename StringType, typename... Args>
4245inline std::size_t concat_length(const StringType& str, const Args&... rest);
4246
4247template <typename... Args>
4248inline std::size_t concat_length(const char /*c*/, const Args&... rest) {
4249 return 1 + concat_length(rest...);
4250}
4251
4252template <typename... Args>
4253inline std::size_t concat_length(const char* cstr, const Args&... rest) {
4254 // cppcheck-suppress ignoredReturnValue
4255 return ::strlen(cstr) + concat_length(rest...);
4256}
4257
4258template <typename StringType, typename... Args>
4259inline std::size_t concat_length(const StringType& str, const Args&... rest) {
4260 return str.size() + concat_length(rest...);
4261}
4262
4263template <typename OutStringType> inline void concat_into(OutStringType& /*out*/) {}
4264
4265template <typename StringType, typename Arg>
4266using string_can_append = decltype(std::declval<StringType&>().append(std::declval<Arg&&>()));
4267
4268template <typename StringType, typename Arg>
4269using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4270
4271template <typename StringType, typename Arg>
4272using string_can_append_op = decltype(std::declval<StringType&>() += std::declval<Arg&&>());
4273
4274template <typename StringType, typename Arg>
4275using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4276
4277template <typename StringType, typename Arg>
4278using string_can_append_iter = decltype(std::declval<StringType&>().append(
4279 std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4280
4281template <typename StringType, typename Arg>
4282using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4283
4284template <typename StringType, typename Arg>
4285using string_can_append_data = decltype(std::declval<StringType&>().append(
4286 std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4287
4288template <typename StringType, typename Arg>
4289using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4290
4291template <typename OutStringType, typename Arg, typename... Args,
4292 enable_if_t<!detect_string_can_append<OutStringType, Arg>::value &&
4293 detect_string_can_append_op<OutStringType, Arg>::value,
4294 int> = 0>
4295inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest);
4296
4297template <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,
4301 int> = 0>
4302inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
4303
4304template <typename OutStringType, typename Arg, typename... Args,
4305 enable_if_t<!detect_string_can_append<OutStringType, Arg>::value &&
4306 !detect_string_can_append_op<OutStringType, Arg>::value &&
4307 !detect_string_can_append_iter<OutStringType, Arg>::value &&
4308 detect_string_can_append_data<OutStringType, Arg>::value,
4309 int> = 0>
4310inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
4311
4312template <typename OutStringType, typename Arg, typename... Args,
4313 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4314inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest) {
4315 out.append(std::forward<Arg>(arg));
4316 concat_into(out, std::forward<Args>(rest)...);
4317}
4318
4319template <typename OutStringType, typename Arg, typename... Args,
4320 enable_if_t<!detect_string_can_append<OutStringType, Arg>::value &&
4321 detect_string_can_append_op<OutStringType, Arg>::value,
4322 int>>
4323inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest) {
4324 out += std::forward<Arg>(arg);
4325 concat_into(out, std::forward<Args>(rest)...);
4326}
4327
4328template <typename OutStringType, typename Arg, typename... Args,
4329 enable_if_t<!detect_string_can_append<OutStringType, Arg>::value &&
4330 !detect_string_can_append_op<OutStringType, Arg>::value &&
4331 detect_string_can_append_iter<OutStringType, Arg>::value,
4332 int>>
4333inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest) {
4334 out.append(arg.begin(), arg.end());
4335 concat_into(out, std::forward<Args>(rest)...);
4336}
4337
4338template <typename OutStringType, typename Arg, typename... Args,
4339 enable_if_t<!detect_string_can_append<OutStringType, Arg>::value &&
4340 !detect_string_can_append_op<OutStringType, Arg>::value &&
4341 !detect_string_can_append_iter<OutStringType, Arg>::value &&
4342 detect_string_can_append_data<OutStringType, Arg>::value,
4343 int>>
4344inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest) {
4345 out.append(arg.data(), arg.size());
4346 concat_into(out, std::forward<Args>(rest)...);
4347}
4348
4349template <typename OutStringType = std::string, typename... Args>
4350inline OutStringType concat(Args&&... args) {
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
4358NLOHMANN_JSON_NAMESPACE_END
4359
4360NLOHMANN_JSON_NAMESPACE_BEGIN
4361namespace detail {
4362
4364// exceptions //
4366
4369class exception : public std::exception {
4370 public:
4372 const char* what() const noexcept override { return m.what(); }
4373
4375 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4376
4377 protected:
4378 JSON_HEDLEY_NON_NULL(3)
4379 exception(int id_, const char* what_arg)
4380 : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4381
4382 static std::string name(const std::string& ename, int id_) {
4383 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4384 }
4385
4386 static std::string diagnostics(std::nullptr_t /*leaf_element*/) { return ""; }
4387
4388 template <typename BasicJsonType>
4389 static std::string diagnostics(const BasicJsonType* leaf_element) {
4390#if JSON_DIAGNOSTICS
4391 std::vector<std::string> tokens;
4392 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr;
4393 current = current->m_parent) {
4394 switch (current->m_parent->type()) {
4395 case value_t::array: {
4396 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size();
4397 ++i) {
4398 if (&current->m_parent->m_data.m_value.array->operator[](i) == current) {
4399 tokens.emplace_back(std::to_string(i));
4400 break;
4401 }
4402 }
4403 break;
4404 }
4405
4406 case value_t::object: {
4407 for (const auto& element : *current->m_parent->m_data.m_value.object) {
4408 if (&element.second == current) {
4409 tokens.emplace_back(element.first.c_str());
4410 break;
4411 }
4412 }
4413 break;
4414 }
4415
4416 case value_t::null: // LCOV_EXCL_LINE
4417 case value_t::string: // LCOV_EXCL_LINE
4418 case value_t::boolean: // LCOV_EXCL_LINE
4419 case value_t::number_integer: // LCOV_EXCL_LINE
4420 case value_t::number_unsigned: // LCOV_EXCL_LINE
4421 case value_t::number_float: // LCOV_EXCL_LINE
4422 case value_t::binary: // LCOV_EXCL_LINE
4423 case value_t::discarded: // LCOV_EXCL_LINE
4424 default: // LCOV_EXCL_LINE
4425 break; // LCOV_EXCL_LINE
4426 }
4427 }
4428
4429 if (tokens.empty()) {
4430 return "";
4431 }
4432
4433 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4434 [](const std::string& a, const std::string& b) {
4435 return concat(a, '/', detail::escape(b));
4436 });
4437 return concat('(', str, ") ");
4438#else
4439 static_cast<void>(leaf_element);
4440 return "";
4441#endif
4442 }
4443
4444 private:
4446 std::runtime_error m;
4447};
4448
4451class parse_error : public exception {
4452 public:
4462 template <typename BasicJsonContext,
4463 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4464 static parse_error create(int id_, const position_t& pos, const std::string& what_arg,
4465 BasicJsonContext context) {
4466 const std::string w =
4467 concat(exception::name("parse_error", id_), "parse error", position_string(pos), ": ",
4468 exception::diagnostics(context), what_arg);
4469 return {id_, pos.chars_read_total, w.c_str()};
4470 }
4471
4472 template <typename BasicJsonContext,
4473 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4474 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg,
4475 BasicJsonContext context) {
4476 const std::string w =
4477 concat(exception::name("parse_error", id_), "parse error",
4478 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), ": ",
4479 exception::diagnostics(context), what_arg);
4480 return {id_, byte_, w.c_str()};
4481 }
4482
4492 const std::size_t byte;
4493
4494 private:
4495 parse_error(int id_, std::size_t byte_, const char* what_arg)
4496 : exception(id_, what_arg), byte(byte_) {}
4497
4498 static std::string position_string(const position_t& pos) {
4499 return concat(" at line ", std::to_string(pos.lines_read + 1), ", column ",
4500 std::to_string(pos.chars_read_current_line));
4501 }
4502};
4503
4506class invalid_iterator : public exception {
4507 public:
4508 template <typename BasicJsonContext,
4509 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4510 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) {
4511 const std::string w = concat(exception::name("invalid_iterator", id_),
4512 exception::diagnostics(context), what_arg);
4513 return {id_, w.c_str()};
4514 }
4515
4516 private:
4517 JSON_HEDLEY_NON_NULL(3)
4518 invalid_iterator(int id_, const char* what_arg) : exception(id_, what_arg) {}
4519};
4520
4523class type_error : public exception {
4524 public:
4525 template <typename BasicJsonContext,
4526 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4527 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) {
4528 const std::string w =
4529 concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4530 return {id_, w.c_str()};
4531 }
4532
4533 private:
4534 JSON_HEDLEY_NON_NULL(3)
4535 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4536};
4537
4540class out_of_range : public exception {
4541 public:
4542 template <typename BasicJsonContext,
4543 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4544 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) {
4545 const std::string w =
4546 concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4547 return {id_, w.c_str()};
4548 }
4549
4550 private:
4551 JSON_HEDLEY_NON_NULL(3)
4552 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4553};
4554
4557class other_error : public exception {
4558 public:
4559 template <typename BasicJsonContext,
4560 enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4561 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) {
4562 const std::string w =
4563 concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4564 return {id_, w.c_str()};
4565 }
4566
4567 private:
4568 JSON_HEDLEY_NON_NULL(3)
4569 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4570};
4571
4572} // namespace detail
4573NLOHMANN_JSON_NAMESPACE_END
4574
4575// #include <nlohmann/detail/macro_scope.hpp>
4576
4577// #include <nlohmann/detail/meta/cpp_future.hpp>
4578
4579// #include <nlohmann/detail/meta/identity_tag.hpp>
4580// __ _____ _____ _____
4581// __| | __| | | | JSON for Modern C++
4582// | | |__ | | | | | | version 3.11.3
4583// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4584//
4585// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4586// SPDX-License-Identifier: MIT
4587
4588// #include <nlohmann/detail/abi_macros.hpp>
4589
4590NLOHMANN_JSON_NAMESPACE_BEGIN
4591namespace detail {
4592
4593// dispatching helper struct
4594template <class T> struct identity_tag {};
4595
4596} // namespace detail
4597NLOHMANN_JSON_NAMESPACE_END
4598
4599// #include <nlohmann/detail/meta/std_fs.hpp>
4600// __ _____ _____ _____
4601// __| | __| | | | JSON for Modern C++
4602// | | |__ | | | | | | version 3.11.3
4603// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4604//
4605// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4606// SPDX-License-Identifier: MIT
4607
4608// #include <nlohmann/detail/macro_scope.hpp>
4609
4610#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4611#include <experimental/filesystem>
4612NLOHMANN_JSON_NAMESPACE_BEGIN
4613namespace detail {
4614namespace std_fs = std::experimental::filesystem;
4615} // namespace detail
4616NLOHMANN_JSON_NAMESPACE_END
4617#elif JSON_HAS_FILESYSTEM
4618#include <filesystem>
4619NLOHMANN_JSON_NAMESPACE_BEGIN
4620namespace detail {
4621namespace std_fs = std::filesystem;
4622} // namespace detail
4623NLOHMANN_JSON_NAMESPACE_END
4624#endif
4625
4626// #include <nlohmann/detail/meta/type_traits.hpp>
4627
4628// #include <nlohmann/detail/string_concat.hpp>
4629
4630// #include <nlohmann/detail/value_t.hpp>
4631
4632NLOHMANN_JSON_NAMESPACE_BEGIN
4633namespace detail {
4634
4635template <typename BasicJsonType>
4636inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) {
4637 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) {
4638 JSON_THROW(
4639 type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4640 }
4641 n = nullptr;
4642}
4643
4644// overloads for basic_json template parameters
4645template <typename BasicJsonType, typename ArithmeticType,
4646 enable_if_t<std::is_arithmetic<ArithmeticType>::value &&
4647 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4648 int> = 0>
4649void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) {
4650 switch (static_cast<value_t>(j)) {
4652 val = static_cast<ArithmeticType>(
4653 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4654 break;
4655 }
4657 val = static_cast<ArithmeticType>(
4658 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4659 break;
4660 }
4661 case value_t::number_float: {
4662 val = static_cast<ArithmeticType>(
4663 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4664 break;
4665 }
4666
4667 case value_t::null:
4668 case value_t::object:
4669 case value_t::array:
4670 case value_t::string:
4671 case value_t::boolean:
4672 case value_t::binary:
4673 case value_t::discarded:
4674 default:
4675 JSON_THROW(
4676 type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4677 }
4678}
4679
4680template <typename BasicJsonType>
4681inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) {
4682 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) {
4683 JSON_THROW(
4684 type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4685 }
4686 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4687}
4688
4689template <typename BasicJsonType>
4690inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) {
4691 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
4692 JSON_THROW(
4693 type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4694 }
4695 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4696}
4697
4698template <
4699 typename BasicJsonType, typename StringType,
4700 enable_if_t<std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value &&
4701 is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t,
4702 StringType>::value &&
4703 !std::is_same<typename BasicJsonType::string_t, StringType>::value &&
4705 int> = 0>
4706inline void from_json(const BasicJsonType& j, StringType& s) {
4707 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
4708 JSON_THROW(
4709 type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4710 }
4711
4712 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4713}
4714
4715template <typename BasicJsonType>
4716inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) {
4717 get_arithmetic_value(j, val);
4718}
4719
4720template <typename BasicJsonType>
4721inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) {
4722 get_arithmetic_value(j, val);
4723}
4724
4725template <typename BasicJsonType>
4726inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) {
4727 get_arithmetic_value(j, val);
4728}
4729
4730#if !JSON_DISABLE_ENUM_SERIALIZATION
4731template <typename BasicJsonType, typename EnumType,
4732 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4733inline void from_json(const BasicJsonType& j, EnumType& e) {
4734 typename std::underlying_type<EnumType>::type val;
4735 get_arithmetic_value(j, val);
4736 e = static_cast<EnumType>(val);
4737}
4738#endif // JSON_DISABLE_ENUM_SERIALIZATION
4739
4740// forward_list doesn't have an insert method
4741template <typename BasicJsonType, typename T, typename Allocator,
4742 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4743inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) {
4744 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4745 JSON_THROW(
4746 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4747 }
4748 l.clear();
4749 std::transform(j.rbegin(), j.rend(), std::front_inserter(l),
4750 [](const BasicJsonType& i) { return i.template get<T>(); });
4751}
4752
4753// valarray doesn't have an insert method
4754template <typename BasicJsonType, typename T,
4755 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4756inline void from_json(const BasicJsonType& j, std::valarray<T>& l) {
4757 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4758 JSON_THROW(
4759 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4760 }
4761 l.resize(j.size());
4762 std::transform(j.begin(), j.end(), std::begin(l),
4763 [](const BasicJsonType& elem) { return elem.template get<T>(); });
4764}
4765
4766template <typename BasicJsonType, typename T, std::size_t N>
4767auto from_json(
4768 const BasicJsonType& j,
4769 T (&arr)
4770 [N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4771 -> decltype(j.template get<T>(), void()) {
4772 for (std::size_t i = 0; i < N; ++i) {
4773 arr[i] = j.at(i).template get<T>();
4774 }
4775}
4776
4777template <typename BasicJsonType>
4778inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr,
4779 priority_tag<3> /*unused*/) {
4780 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4781}
4782
4783template <typename BasicJsonType, typename T, std::size_t N>
4784auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
4785 -> decltype(j.template get<T>(), void()) {
4786 for (std::size_t i = 0; i < N; ++i) {
4787 arr[i] = j.at(i).template get<T>();
4788 }
4789}
4790
4791template <typename BasicJsonType, typename ConstructibleArrayType,
4792 enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4793 int> = 0>
4794auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4795 priority_tag<1> /*unused*/)
4796 -> decltype(arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4797 j.template get<typename ConstructibleArrayType::value_type>(), void()) {
4798 using std::end;
4799
4800 ConstructibleArrayType ret;
4801 ret.reserve(j.size());
4802 std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
4803 // get<BasicJsonType>() returns *this, this won't call a from_json
4804 // method when value_type is BasicJsonType
4805 return i.template get<typename ConstructibleArrayType::value_type>();
4806 });
4807 arr = std::move(ret);
4808}
4809
4810template <typename BasicJsonType, typename ConstructibleArrayType,
4811 enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4812 int> = 0>
4813inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4814 priority_tag<0> /*unused*/) {
4815 using std::end;
4816
4817 ConstructibleArrayType ret;
4818 std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
4819 // get<BasicJsonType>() returns *this, this won't call a from_json
4820 // method when value_type is BasicJsonType
4821 return i.template get<typename ConstructibleArrayType::value_type>();
4822 });
4823 arr = std::move(ret);
4824}
4825
4826template <typename BasicJsonType, typename ConstructibleArrayType,
4827 enable_if_t<
4830 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value &&
4831 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value &&
4833 int> = 0>
4834auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4835 -> decltype(from_json_array_impl(j, arr, priority_tag<3>{}),
4836 j.template get<typename ConstructibleArrayType::value_type>(), void()) {
4837 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4838 JSON_THROW(
4839 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4840 }
4841
4842 from_json_array_impl(j, arr, priority_tag<3>{});
4843}
4844
4845template <typename BasicJsonType, typename T, std::size_t... Idx>
4846std::array<T, sizeof...(Idx)>
4847from_json_inplace_array_impl(BasicJsonType&& j,
4848 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/,
4849 index_sequence<Idx...> /*unused*/) {
4850 return {{std::forward<BasicJsonType>(j).at(Idx).template get<T>()...}};
4851}
4852
4853template <typename BasicJsonType, typename T, std::size_t N>
4854auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4855 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag,
4856 make_index_sequence<N>{})) {
4857 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4858 JSON_THROW(
4859 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4860 }
4861
4862 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag,
4863 make_index_sequence<N>{});
4864}
4865
4866template <typename BasicJsonType>
4867inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) {
4868 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) {
4869 JSON_THROW(
4870 type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4871 }
4872
4873 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4874}
4875
4876template <typename BasicJsonType, typename ConstructibleObjectType,
4877 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value,
4878 int> = 0>
4879inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) {
4880 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) {
4881 JSON_THROW(
4882 type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4883 }
4884
4885 ConstructibleObjectType ret;
4886 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4887 using value_type = typename ConstructibleObjectType::value_type;
4888 std::transform(inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()),
4889 [](typename BasicJsonType::object_t::value_type const& p) {
4890 return value_type(
4891 p.first,
4892 p.second.template get<typename ConstructibleObjectType::mapped_type>());
4893 });
4894 obj = std::move(ret);
4895}
4896
4897// overload for arithmetic types, not chosen for basic_json template arguments
4898// (BooleanType, etc..); note: Is it really necessary to provide explicit
4899// overloads for boolean_t etc. in case of a custom BooleanType which is not
4900// an arithmetic type?
4901template <typename BasicJsonType, typename ArithmeticType,
4902 enable_if_t<
4903 std::is_arithmetic<ArithmeticType>::value &&
4904 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value &&
4905 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value &&
4906 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value &&
4907 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4908 int> = 0>
4909inline void from_json(const BasicJsonType& j, ArithmeticType& val) {
4910 switch (static_cast<value_t>(j)) {
4912 val = static_cast<ArithmeticType>(
4913 *j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4914 break;
4915 }
4917 val = static_cast<ArithmeticType>(
4918 *j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4919 break;
4920 }
4921 case value_t::number_float: {
4922 val = static_cast<ArithmeticType>(
4923 *j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4924 break;
4925 }
4926 case value_t::boolean: {
4927 val = static_cast<ArithmeticType>(
4928 *j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4929 break;
4930 }
4931
4932 case value_t::null:
4933 case value_t::object:
4934 case value_t::array:
4935 case value_t::string:
4936 case value_t::binary:
4937 case value_t::discarded:
4938 default:
4939 JSON_THROW(
4940 type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4941 }
4942}
4943
4944template <typename BasicJsonType, typename... Args, std::size_t... Idx>
4945std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j,
4946 index_sequence<Idx...> /*unused*/) {
4947 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4948}
4949
4950template <typename BasicJsonType, class A1, class A2>
4951std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j,
4952 identity_tag<std::pair<A1, A2>> /*unused*/,
4953 priority_tag<0> /*unused*/) {
4954 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4955 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4956}
4957
4958template <typename BasicJsonType, typename A1, typename A2>
4959inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p,
4960 priority_tag<1> /*unused*/) {
4961 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>>{},
4962 priority_tag<0>{});
4963}
4964
4965template <typename BasicJsonType, typename... Args>
4966std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j,
4967 identity_tag<std::tuple<Args...>> /*unused*/,
4968 priority_tag<2> /*unused*/) {
4969 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j),
4970 index_sequence_for<Args...>{});
4971}
4972
4973template <typename BasicJsonType, typename... Args>
4974inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t,
4975 priority_tag<3> /*unused*/) {
4976 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j),
4977 index_sequence_for<Args...>{});
4978}
4979
4980template <typename BasicJsonType, typename TupleRelated>
4981auto from_json(BasicJsonType&& j, TupleRelated&& t)
4982 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t),
4983 priority_tag<3>{})) {
4984 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4985 JSON_THROW(
4986 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4987 }
4988
4989 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t),
4990 priority_tag<3>{});
4991}
4992
4993template <
4994 typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4995 typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
4996inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) {
4997 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
4998 JSON_THROW(
4999 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5000 }
5001 m.clear();
5002 for (const auto& p : j) {
5003 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
5004 JSON_THROW(
5005 type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5006 }
5007 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5008 }
5009}
5010
5011template <
5012 typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual,
5013 typename Allocator,
5014 typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
5015inline void from_json(const BasicJsonType& j,
5016 std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) {
5017 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) {
5018 JSON_THROW(
5019 type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5020 }
5021 m.clear();
5022 for (const auto& p : j) {
5023 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) {
5024 JSON_THROW(
5025 type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5026 }
5027 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5028 }
5029}
5030
5031#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5032template <typename BasicJsonType> inline void from_json(const BasicJsonType& j, std_fs::path& p) {
5033 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) {
5034 JSON_THROW(
5035 type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5036 }
5037 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5038}
5039#endif
5040
5042 template <typename BasicJsonType, typename T>
5043 auto operator()(const BasicJsonType& j, T&& val) const
5044 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5045 -> decltype(from_json(j, std::forward<T>(val))) {
5046 return from_json(j, std::forward<T>(val));
5047 }
5048};
5049
5050} // namespace detail
5051
5052#ifndef JSON_HAS_CPP_17
5056namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5057{
5058#endif
5059JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5060 detail::static_const<detail::from_json_fn>::value;
5061#ifndef JSON_HAS_CPP_17
5062} // namespace
5063#endif
5064
5065NLOHMANN_JSON_NAMESPACE_END
5066
5067// #include <nlohmann/detail/conversions/to_json.hpp>
5068// __ _____ _____ _____
5069// __| | __| | | | JSON for Modern C++
5070// | | |__ | | | | | | version 3.11.3
5071// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5072//
5073// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5074// SPDX-License-Identifier: MIT
5075
5076#include <algorithm> // copy
5077#include <iterator> // begin, end
5078#include <string> // string
5079#include <tuple> // tuple, get
5080#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5081#include <utility> // move, forward, declval, pair
5082#include <valarray> // valarray
5083#include <vector> // vector
5084
5085// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5086// __ _____ _____ _____
5087// __| | __| | | | JSON for Modern C++
5088// | | |__ | | | | | | version 3.11.3
5089// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5090//
5091// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5092// SPDX-License-Identifier: MIT
5093
5094#include <cstddef> // size_t
5095#include <iterator> // input_iterator_tag
5096#include <string> // string, to_string
5097#include <tuple> // tuple_size, get, tuple_element
5098#include <utility> // move
5099
5100#if JSON_HAS_RANGES
5101#include <ranges> // enable_borrowed_range
5102#endif
5103
5104// #include <nlohmann/detail/abi_macros.hpp>
5105
5106// #include <nlohmann/detail/meta/type_traits.hpp>
5107
5108// #include <nlohmann/detail/value_t.hpp>
5109
5110NLOHMANN_JSON_NAMESPACE_BEGIN
5111namespace detail {
5112
5113template <typename string_type> void int_to_string(string_type& target, std::size_t value) {
5114 // For ADL
5115 using std::to_string;
5116 target = to_string(value);
5117}
5118template <typename IteratorType> class iteration_proxy_value {
5119 public:
5120 using difference_type = std::ptrdiff_t;
5121 using value_type = iteration_proxy_value;
5122 using pointer = value_type*;
5123 using reference = value_type&;
5124 using iterator_category = std::input_iterator_tag;
5125 using string_type = typename std::remove_cv<
5126 typename std::remove_reference<decltype(std::declval<IteratorType>().key())>::type>::type;
5127
5128 private:
5130 IteratorType anchor{};
5132 std::size_t array_index = 0;
5134 mutable std::size_t array_index_last = 0;
5136 mutable string_type array_index_str = "0";
5138 string_type empty_str{};
5139
5140 public:
5141 explicit iteration_proxy_value() = default;
5142 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) noexcept(
5143 std::is_nothrow_move_constructible<IteratorType>::value &&
5144 std::is_nothrow_default_constructible<string_type>::value)
5145 : anchor(std::move(it)), array_index(array_index_) {}
5146
5147 iteration_proxy_value(iteration_proxy_value const&) = default;
5148 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5149 // older GCCs are a bit fussy and require explicit noexcept specifiers on
5150 // defaulted functions
5151 iteration_proxy_value(iteration_proxy_value&&) noexcept(
5152 std::is_nothrow_move_constructible<IteratorType>::value &&
5153 std::is_nothrow_move_constructible<string_type>::value) =
5154 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5155 iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(
5156 std::is_nothrow_move_assignable<IteratorType>::value &&
5157 std::is_nothrow_move_assignable<string_type>::value) =
5158 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5159 ~iteration_proxy_value() = default;
5160
5162 const iteration_proxy_value& operator*() const { return *this; }
5163
5165 iteration_proxy_value& operator++() {
5166 ++anchor;
5167 ++array_index;
5168
5169 return *this;
5170 }
5171
5172 iteration_proxy_value operator++(int) & // NOLINT(cert-dcl21-cpp)
5173 {
5174 auto tmp = iteration_proxy_value(anchor, array_index);
5175 ++anchor;
5176 ++array_index;
5177 return tmp;
5178 }
5179
5181 bool operator==(const iteration_proxy_value& o) const { return anchor == o.anchor; }
5182
5184 bool operator!=(const iteration_proxy_value& o) const { return anchor != o.anchor; }
5185
5187 const string_type& key() const {
5188 JSON_ASSERT(anchor.m_object != nullptr);
5189
5190 switch (anchor.m_object->type()) {
5191 // use integer array index as key
5192 case value_t::array: {
5193 if (array_index != array_index_last) {
5194 int_to_string(array_index_str, array_index);
5195 array_index_last = array_index;
5196 }
5197 return array_index_str;
5198 }
5199
5200 // use key from the object
5201 case value_t::object:
5202 return anchor.key();
5203
5204 // use an empty key for all primitive types
5205 case value_t::null:
5206 case value_t::string:
5207 case value_t::boolean:
5211 case value_t::binary:
5212 case value_t::discarded:
5213 default:
5214 return empty_str;
5215 }
5216 }
5217
5219 typename IteratorType::reference value() const { return anchor.value(); }
5220};
5221
5223template <typename IteratorType> class iteration_proxy {
5224 private:
5226 typename IteratorType::pointer container = nullptr;
5227
5228 public:
5229 explicit iteration_proxy() = default;
5230
5232 explicit iteration_proxy(typename IteratorType::reference cont) noexcept : container(&cont) {}
5233
5234 iteration_proxy(iteration_proxy const&) = default;
5235 iteration_proxy& operator=(iteration_proxy const&) = default;
5236 iteration_proxy(iteration_proxy&&) noexcept = default;
5237 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5238 ~iteration_proxy() = default;
5239
5241 iteration_proxy_value<IteratorType> begin() const noexcept {
5242 return iteration_proxy_value<IteratorType>(container->begin());
5243 }
5244
5247 return iteration_proxy_value<IteratorType>(container->end());
5248 }
5249};
5250
5251// Structured Bindings Support
5252// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5253// And see https://github.com/nlohmann/json/pull/1391
5254template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5255auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) {
5256 return i.key();
5257}
5258// Structured Bindings Support
5259// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5260// And see https://github.com/nlohmann/json/pull/1391
5261template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5262auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) {
5263 return i.value();
5264}
5265
5266} // namespace detail
5267NLOHMANN_JSON_NAMESPACE_END
5268
5269// The Addition to the STD Namespace is required to add
5270// Structured Bindings Support to the iteration_proxy_value class
5271// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5272// And see https://github.com/nlohmann/json/pull/1391
5273namespace std {
5274
5275#if defined(__clang__)
5276// Fix: https://github.com/nlohmann/json/issues/1401
5277#pragma clang diagnostic push
5278#pragma clang diagnostic ignored "-Wmismatched-tags"
5279#endif
5280template <typename IteratorType>
5281class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5282 : public std::integral_constant<std::size_t, 2> {};
5283
5284template <std::size_t N, typename IteratorType>
5285class tuple_element<
5286 N, ::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5287{
5288 public:
5289 using type =
5290 decltype(get<N>(std::declval<::nlohmann::detail::iteration_proxy_value<IteratorType>>()));
5291};
5292#if defined(__clang__)
5293#pragma clang diagnostic pop
5294#endif
5295
5296} // namespace std
5297
5298#if JSON_HAS_RANGES
5299template <typename IteratorType>
5300inline constexpr bool ::std::ranges::enable_borrowed_range<
5301 ::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5302#endif
5303
5304// #include <nlohmann/detail/macro_scope.hpp>
5305
5306// #include <nlohmann/detail/meta/cpp_future.hpp>
5307
5308// #include <nlohmann/detail/meta/std_fs.hpp>
5309
5310// #include <nlohmann/detail/meta/type_traits.hpp>
5311
5312// #include <nlohmann/detail/value_t.hpp>
5313
5314NLOHMANN_JSON_NAMESPACE_BEGIN
5315namespace detail {
5316
5318// constructors //
5320
5321/*
5322 * Note all external_constructor<>::construct functions need to call
5323 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j
5324 * contains an allocated value (e.g., a string). See bug issue
5325 * https://github.com/nlohmann/json/issues/2865 for more information.
5326 */
5327
5328template <value_t> struct external_constructor;
5329
5331 template <typename BasicJsonType>
5332 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept {
5333 j.m_data.m_value.destroy(j.m_data.m_type);
5334 j.m_data.m_type = value_t::boolean;
5335 j.m_data.m_value = b;
5336 j.assert_invariant();
5337 }
5338};
5339
5341 template <typename BasicJsonType>
5342 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) {
5343 j.m_data.m_value.destroy(j.m_data.m_type);
5344 j.m_data.m_type = value_t::string;
5345 j.m_data.m_value = s;
5346 j.assert_invariant();
5347 }
5348
5349 template <typename BasicJsonType>
5350 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) {
5351 j.m_data.m_value.destroy(j.m_data.m_type);
5352 j.m_data.m_type = value_t::string;
5353 j.m_data.m_value = std::move(s);
5354 j.assert_invariant();
5355 }
5356
5357 template <
5358 typename BasicJsonType, typename CompatibleStringType,
5359 enable_if_t<!std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5360 int> = 0>
5361 static void construct(BasicJsonType& j, const CompatibleStringType& str) {
5362 j.m_data.m_value.destroy(j.m_data.m_type);
5363 j.m_data.m_type = value_t::string;
5364 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5365 j.assert_invariant();
5366 }
5367};
5368
5370 template <typename BasicJsonType>
5371 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) {
5372 j.m_data.m_value.destroy(j.m_data.m_type);
5373 j.m_data.m_type = value_t::binary;
5374 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5375 j.assert_invariant();
5376 }
5377
5378 template <typename BasicJsonType>
5379 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) {
5380 j.m_data.m_value.destroy(j.m_data.m_type);
5381 j.m_data.m_type = value_t::binary;
5382 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5383 j.assert_invariant();
5384 }
5385};
5386
5388 template <typename BasicJsonType>
5389 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept {
5390 j.m_data.m_value.destroy(j.m_data.m_type);
5391 j.m_data.m_type = value_t::number_float;
5392 j.m_data.m_value = val;
5393 j.assert_invariant();
5394 }
5395};
5396
5398 template <typename BasicJsonType>
5399 static void construct(BasicJsonType& j,
5400 typename BasicJsonType::number_unsigned_t val) noexcept {
5401 j.m_data.m_value.destroy(j.m_data.m_type);
5402 j.m_data.m_type = value_t::number_unsigned;
5403 j.m_data.m_value = val;
5404 j.assert_invariant();
5405 }
5406};
5407
5409 template <typename BasicJsonType>
5410 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept {
5411 j.m_data.m_value.destroy(j.m_data.m_type);
5412 j.m_data.m_type = value_t::number_integer;
5413 j.m_data.m_value = val;
5414 j.assert_invariant();
5415 }
5416};
5417
5418template <> struct external_constructor<value_t::array> {
5419 template <typename BasicJsonType>
5420 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) {
5421 j.m_data.m_value.destroy(j.m_data.m_type);
5422 j.m_data.m_type = value_t::array;
5423 j.m_data.m_value = arr;
5424 j.set_parents();
5425 j.assert_invariant();
5426 }
5427
5428 template <typename BasicJsonType>
5429 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) {
5430 j.m_data.m_value.destroy(j.m_data.m_type);
5431 j.m_data.m_type = value_t::array;
5432 j.m_data.m_value = std::move(arr);
5433 j.set_parents();
5434 j.assert_invariant();
5435 }
5436
5437 template <
5438 typename BasicJsonType, typename CompatibleArrayType,
5439 enable_if_t<!std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5440 int> = 0>
5441 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) {
5442 using std::begin;
5443 using std::end;
5444
5445 j.m_data.m_value.destroy(j.m_data.m_type);
5446 j.m_data.m_type = value_t::array;
5447 j.m_data.m_value.array =
5448 j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5449 j.set_parents();
5450 j.assert_invariant();
5451 }
5452
5453 template <typename BasicJsonType>
5454 static void construct(BasicJsonType& j, const std::vector<bool>& arr) {
5455 j.m_data.m_value.destroy(j.m_data.m_type);
5456 j.m_data.m_type = value_t::array;
5457 j.m_data.m_value = value_t::array;
5458 j.m_data.m_value.array->reserve(arr.size());
5459 for (const bool x : arr) {
5460 j.m_data.m_value.array->push_back(x);
5461 j.set_parent(j.m_data.m_value.array->back());
5462 }
5463 j.assert_invariant();
5464 }
5465
5466 template <typename BasicJsonType, typename T,
5467 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5468 static void construct(BasicJsonType& j, const std::valarray<T>& arr) {
5469 j.m_data.m_value.destroy(j.m_data.m_type);
5470 j.m_data.m_type = value_t::array;
5471 j.m_data.m_value = value_t::array;
5472 j.m_data.m_value.array->resize(arr.size());
5473 if (arr.size() > 0) {
5474 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5475 }
5476 j.set_parents();
5477 j.assert_invariant();
5478 }
5479};
5480
5482 template <typename BasicJsonType>
5483 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) {
5484 j.m_data.m_value.destroy(j.m_data.m_type);
5485 j.m_data.m_type = value_t::object;
5486 j.m_data.m_value = obj;
5487 j.set_parents();
5488 j.assert_invariant();
5489 }
5490
5491 template <typename BasicJsonType>
5492 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) {
5493 j.m_data.m_value.destroy(j.m_data.m_type);
5494 j.m_data.m_type = value_t::object;
5495 j.m_data.m_value = std::move(obj);
5496 j.set_parents();
5497 j.assert_invariant();
5498 }
5499
5500 template <
5501 typename BasicJsonType, typename CompatibleObjectType,
5502 enable_if_t<!std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value,
5503 int> = 0>
5504 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) {
5505 using std::begin;
5506 using std::end;
5507
5508 j.m_data.m_value.destroy(j.m_data.m_type);
5509 j.m_data.m_type = value_t::object;
5510 j.m_data.m_value.object =
5511 j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5512 j.set_parents();
5513 j.assert_invariant();
5514 }
5515};
5516
5518// to_json //
5520
5521template <typename BasicJsonType, typename T,
5522 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5523inline void to_json(BasicJsonType& j, T b) noexcept {
5525}
5526
5527template <
5528 typename BasicJsonType, typename BoolRef,
5529 enable_if_t<
5530 ((std::is_same<std::vector<bool>::reference, BoolRef>::value &&
5531 !std::is_same<std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) ||
5532 (std::is_same<std::vector<bool>::const_reference, BoolRef>::value &&
5533 !std::is_same<detail::uncvref_t<std::vector<bool>::const_reference>,
5534 typename BasicJsonType::boolean_t>::value)) &&
5535 std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value,
5536 int> = 0>
5537inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept {
5538 external_constructor<value_t::boolean>::construct(
5539 j, static_cast<typename BasicJsonType::boolean_t>(b));
5540}
5541
5542template <
5543 typename BasicJsonType, typename CompatibleString,
5544 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value,
5545 int> = 0>
5546inline void to_json(BasicJsonType& j, const CompatibleString& s) {
5548}
5549
5550template <typename BasicJsonType>
5551inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) {
5553}
5554
5555template <typename BasicJsonType, typename FloatType,
5556 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5557inline void to_json(BasicJsonType& j, FloatType val) noexcept {
5559 j, static_cast<typename BasicJsonType::number_float_t>(val));
5560}
5561
5562template <typename BasicJsonType, typename CompatibleNumberUnsignedType,
5563 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t,
5564 CompatibleNumberUnsignedType>::value,
5565 int> = 0>
5566inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept {
5568 j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5569}
5570
5571template <typename BasicJsonType, typename CompatibleNumberIntegerType,
5572 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t,
5573 CompatibleNumberIntegerType>::value,
5574 int> = 0>
5575inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept {
5577 j, static_cast<typename BasicJsonType::number_integer_t>(val));
5578}
5579
5580#if !JSON_DISABLE_ENUM_SERIALIZATION
5581template <typename BasicJsonType, typename EnumType,
5582 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5583inline void to_json(BasicJsonType& j, EnumType e) noexcept {
5584 using underlying_type = typename std::underlying_type<EnumType>::type;
5585 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value
5588 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5589}
5590#endif // JSON_DISABLE_ENUM_SERIALIZATION
5591
5592template <typename BasicJsonType>
5593inline void to_json(BasicJsonType& j, const std::vector<bool>& e) {
5595}
5596
5597template <
5598 typename BasicJsonType, typename CompatibleArrayType,
5599 enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value &&
5601 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value &&
5602 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value &&
5604 int> = 0>
5605inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) {
5607}
5608
5609template <typename BasicJsonType>
5610inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) {
5612}
5613
5614template <typename BasicJsonType, typename T,
5615 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5616inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) {
5618}
5619
5620template <typename BasicJsonType>
5621inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) {
5623}
5624
5625template <typename BasicJsonType, typename CompatibleObjectType,
5626 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value &&
5628 int> = 0>
5629inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) {
5631}
5632
5633template <typename BasicJsonType>
5634inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) {
5636}
5637
5638template <
5639 typename BasicJsonType, typename T, std::size_t N,
5640 enable_if_t<
5641 !std::is_constructible<typename BasicJsonType::string_t,
5642 const T (&)[N]>::
5643 value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5644 int> = 0>
5645inline void to_json(
5646 BasicJsonType& j,
5647 const T (&arr)
5648 [N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5649{
5651}
5652
5653template <typename BasicJsonType, typename T1, typename T2,
5654 enable_if_t<std::is_constructible<BasicJsonType, T1>::value &&
5655 std::is_constructible<BasicJsonType, T2>::value,
5656 int> = 0>
5657inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) {
5658 j = {p.first, p.second};
5659}
5660
5661// for https://github.com/nlohmann/json/pull/1134
5662template <
5663 typename BasicJsonType, typename T,
5664 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value,
5665 int> = 0>
5666inline void to_json(BasicJsonType& j, const T& b) {
5667 j = {{b.key(), b.value()}};
5668}
5669
5670template <typename BasicJsonType, typename Tuple, std::size_t... Idx>
5671inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t,
5672 index_sequence<Idx...> /*unused*/) {
5673 j = {std::get<Idx>(t)...};
5674}
5675
5676template <typename BasicJsonType, typename T,
5677 enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int> = 0>
5678inline void to_json(BasicJsonType& j, const T& t) {
5679 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value>{});
5680}
5681
5682#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5683template <typename BasicJsonType> inline void to_json(BasicJsonType& j, const std_fs::path& p) {
5684 j = p.string();
5685}
5686#endif
5687
5689 template <typename BasicJsonType, typename T>
5690 auto operator()(BasicJsonType& j, T&& val) const
5691 noexcept(noexcept(to_json(j, std::forward<T>(val))))
5692 -> decltype(to_json(j, std::forward<T>(val)), void()) {
5693 return to_json(j, std::forward<T>(val));
5694 }
5695};
5696} // namespace detail
5697
5698#ifndef JSON_HAS_CPP_17
5702namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5703{
5704#endif
5705JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5706 detail::static_const<detail::to_json_fn>::value;
5707#ifndef JSON_HAS_CPP_17
5708} // namespace
5709#endif
5710
5711NLOHMANN_JSON_NAMESPACE_END
5712
5713// #include <nlohmann/detail/meta/identity_tag.hpp>
5714
5715NLOHMANN_JSON_NAMESPACE_BEGIN
5716
5718template <typename ValueType, typename> struct adl_serializer {
5721 template <typename BasicJsonType, typename TargetType = ValueType>
5722 static auto from_json(BasicJsonType&& j, TargetType& val) noexcept(
5723 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5724 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) {
5725 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5726 }
5727
5730 template <typename BasicJsonType, typename TargetType = ValueType>
5731 static auto from_json(BasicJsonType&& j) noexcept(noexcept(
5732 ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{})))
5733 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j),
5735 return ::nlohmann::from_json(std::forward<BasicJsonType>(j),
5736 detail::identity_tag<TargetType>{});
5737 }
5738
5741 template <typename BasicJsonType, typename TargetType = ValueType>
5742 static auto to_json(BasicJsonType& j, TargetType&& val) noexcept(
5743 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5744 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) {
5745 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5746 }
5747};
5748
5749NLOHMANN_JSON_NAMESPACE_END
5750
5751// #include <nlohmann/byte_container_with_subtype.hpp>
5752// __ _____ _____ _____
5753// __| | __| | | | JSON for Modern C++
5754// | | |__ | | | | | | version 3.11.3
5755// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5756//
5757// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5758// SPDX-License-Identifier: MIT
5759
5760#include <cstdint> // uint8_t, uint64_t
5761#include <tuple> // tie
5762#include <utility> // move
5763
5764// #include <nlohmann/detail/abi_macros.hpp>
5765
5766NLOHMANN_JSON_NAMESPACE_BEGIN
5767
5770template <typename BinaryType> class byte_container_with_subtype : public BinaryType {
5771 public:
5772 using container_type = BinaryType;
5773 using subtype_type = std::uint64_t;
5774
5777 byte_container_with_subtype() noexcept(noexcept(container_type())) : container_type() {}
5778
5781 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5782 : container_type(b) {}
5783
5786 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5787 : container_type(std::move(b)) {}
5788
5791 byte_container_with_subtype(const container_type& b,
5792 subtype_type subtype_) noexcept(noexcept(container_type(b)))
5793 : container_type(b), m_subtype(subtype_), m_has_subtype(true) {}
5794
5797 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(
5798 noexcept(container_type(std::move(b))))
5799 : container_type(std::move(b)), m_subtype(subtype_), m_has_subtype(true) {}
5800
5801 bool operator==(const byte_container_with_subtype& rhs) const {
5802 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5803 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5804 }
5805
5806 bool operator!=(const byte_container_with_subtype& rhs) const { return !(rhs == *this); }
5807
5810 void set_subtype(subtype_type subtype_) noexcept {
5811 m_subtype = subtype_;
5812 m_has_subtype = true;
5813 }
5814
5817 constexpr subtype_type subtype() const noexcept {
5818 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5819 }
5820
5823 constexpr bool has_subtype() const noexcept { return m_has_subtype; }
5824
5828 void clear_subtype() noexcept {
5829 m_subtype = 0;
5830 m_has_subtype = false;
5831 }
5832
5833 private:
5834 subtype_type m_subtype = 0;
5835 bool m_has_subtype = false;
5836};
5837
5838NLOHMANN_JSON_NAMESPACE_END
5839
5840// #include <nlohmann/detail/conversions/from_json.hpp>
5841
5842// #include <nlohmann/detail/conversions/to_json.hpp>
5843
5844// #include <nlohmann/detail/exceptions.hpp>
5845
5846// #include <nlohmann/detail/hash.hpp>
5847// __ _____ _____ _____
5848// __| | __| | | | JSON for Modern C++
5849// | | |__ | | | | | | version 3.11.3
5850// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5851//
5852// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5853// SPDX-License-Identifier: MIT
5854
5855#include <cstddef> // size_t
5856#include <cstdint> // uint8_t
5857#include <functional> // hash
5858
5859// #include <nlohmann/detail/abi_macros.hpp>
5860
5861// #include <nlohmann/detail/value_t.hpp>
5862
5863NLOHMANN_JSON_NAMESPACE_BEGIN
5864namespace detail {
5865
5866// boost::hash_combine
5867inline std::size_t combine(std::size_t seed, std::size_t h) noexcept {
5868 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5869 return seed;
5870}
5871
5883template <typename BasicJsonType> std::size_t hash(const BasicJsonType& j) {
5884 using string_t = typename BasicJsonType::string_t;
5885 using number_integer_t = typename BasicJsonType::number_integer_t;
5886 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5887 using number_float_t = typename BasicJsonType::number_float_t;
5888
5889 const auto type = static_cast<std::size_t>(j.type());
5890 switch (j.type()) {
5891 case BasicJsonType::value_t::null:
5892 case BasicJsonType::value_t::discarded: {
5893 return combine(type, 0);
5894 }
5895
5896 case BasicJsonType::value_t::object: {
5897 auto seed = combine(type, j.size());
5898 for (const auto& element : j.items()) {
5899 const auto h = std::hash<string_t>{}(element.key());
5900 seed = combine(seed, h);
5901 seed = combine(seed, hash(element.value()));
5902 }
5903 return seed;
5904 }
5905
5906 case BasicJsonType::value_t::array: {
5907 auto seed = combine(type, j.size());
5908 for (const auto& element : j) {
5909 seed = combine(seed, hash(element));
5910 }
5911 return seed;
5912 }
5913
5914 case BasicJsonType::value_t::string: {
5915 const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
5916 return combine(type, h);
5917 }
5918
5919 case BasicJsonType::value_t::boolean: {
5920 const auto h = std::hash<bool>{}(j.template get<bool>());
5921 return combine(type, h);
5922 }
5923
5924 case BasicJsonType::value_t::number_integer: {
5925 const auto h = std::hash<number_integer_t>{}(j.template get<number_integer_t>());
5926 return combine(type, h);
5927 }
5928
5929 case BasicJsonType::value_t::number_unsigned: {
5930 const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
5931 return combine(type, h);
5932 }
5933
5934 case BasicJsonType::value_t::number_float: {
5935 const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
5936 return combine(type, h);
5937 }
5938
5939 case BasicJsonType::value_t::binary: {
5940 auto seed = combine(type, j.get_binary().size());
5941 const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
5942 seed = combine(seed, h);
5943 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
5944 for (const auto byte : j.get_binary()) {
5945 seed = combine(seed, std::hash<std::uint8_t>{}(byte));
5946 }
5947 return seed;
5948 }
5949
5950 default: // LCOV_EXCL_LINE
5951 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
5952 // LCOV_EXCL_LINE
5953 return 0; // LCOV_EXCL_LINE
5954 }
5955}
5956
5957} // namespace detail
5958NLOHMANN_JSON_NAMESPACE_END
5959
5960// #include <nlohmann/detail/input/binary_reader.hpp>
5961// __ _____ _____ _____
5962// __| | __| | | | JSON for Modern C++
5963// | | |__ | | | | | | version 3.11.3
5964// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5965//
5966// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5967// SPDX-License-Identifier: MIT
5968
5969#include <algorithm> // generate_n
5970#include <array> // array
5971#include <cmath> // ldexp
5972#include <cstddef> // size_t
5973#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
5974#include <cstdio> // snprintf
5975#include <cstring> // memcpy
5976#include <iterator> // back_inserter
5977#include <limits> // numeric_limits
5978#include <string> // char_traits, string
5979#include <utility> // make_pair, move
5980#include <vector> // vector
5981
5982// #include <nlohmann/detail/exceptions.hpp>
5983
5984// #include <nlohmann/detail/input/input_adapters.hpp>
5985// __ _____ _____ _____
5986// __| | __| | | | JSON for Modern C++
5987// | | |__ | | | | | | version 3.11.3
5988// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5989//
5990// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5991// SPDX-License-Identifier: MIT
5992
5993#include <array> // array
5994#include <cstddef> // size_t
5995#include <cstring> // strlen
5996#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
5997#include <memory> // shared_ptr, make_shared, addressof
5998#include <numeric> // accumulate
5999#include <string> // string, char_traits
6000#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6001#include <utility> // pair, declval
6002
6003#ifndef JSON_NO_IO
6004#include <cstdio> // FILE *
6005#include <istream> // istream
6006#endif // JSON_NO_IO
6007
6008// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6009
6010// #include <nlohmann/detail/macro_scope.hpp>
6011
6012// #include <nlohmann/detail/meta/type_traits.hpp>
6013
6014NLOHMANN_JSON_NAMESPACE_BEGIN
6015namespace detail {
6016
6018enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6019
6021// input adapters //
6023
6024#ifndef JSON_NO_IO
6029class file_input_adapter {
6030 public:
6031 using char_type = char;
6032
6033 JSON_HEDLEY_NON_NULL(2)
6034 explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) {
6035 JSON_ASSERT(m_file != nullptr);
6036 }
6037
6038 // make class move-only
6039 file_input_adapter(const file_input_adapter&) = delete;
6040 file_input_adapter(file_input_adapter&&) noexcept = default;
6041 file_input_adapter& operator=(const file_input_adapter&) = delete;
6042 file_input_adapter& operator=(file_input_adapter&&) = delete;
6043 ~file_input_adapter() = default;
6044
6045 std::char_traits<char>::int_type get_character() noexcept { return std::fgetc(m_file); }
6046
6047 private:
6049 std::FILE* m_file;
6050};
6051
6061class input_stream_adapter {
6062 public:
6063 using char_type = char;
6064
6065 ~input_stream_adapter() {
6066 // clear stream flags; we use underlying streambuf I/O, do not
6067 // maintain ifstream flags, except eof
6068 if (is != nullptr) {
6069 is->clear(is->rdstate() & std::ios::eofbit);
6070 }
6071 }
6072
6073 explicit input_stream_adapter(std::istream& i) : is(&i), sb(i.rdbuf()) {}
6074
6075 // delete because of pointer members
6076 input_stream_adapter(const input_stream_adapter&) = delete;
6077 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6078 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6079
6080 input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) {
6081 rhs.is = nullptr;
6082 rhs.sb = nullptr;
6083 }
6084
6085 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6086 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6087 // end up as the same value, e.g. 0xFFFFFFFF.
6088 std::char_traits<char>::int_type get_character() {
6089 auto res = sb->sbumpc();
6090 // set eof manually, as we don't use the istream interface.
6091 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) {
6092 is->clear(is->rdstate() | std::ios::eofbit);
6093 }
6094 return res;
6095 }
6096
6097 private:
6099 std::istream* is = nullptr;
6100 std::streambuf* sb = nullptr;
6101};
6102#endif // JSON_NO_IO
6103
6104// General-purpose iterator-based adapter. It might not be as fast as
6105// theoretically possible for some containers, but it is extremely versatile.
6106template <typename IteratorType> class iterator_input_adapter {
6107 public:
6108 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6109
6110 iterator_input_adapter(IteratorType first, IteratorType last)
6111 : current(std::move(first)), end(std::move(last)) {}
6112
6113 typename char_traits<char_type>::int_type get_character() {
6114 if (JSON_HEDLEY_LIKELY(current != end)) {
6115 auto result = char_traits<char_type>::to_int_type(*current);
6116 std::advance(current, 1);
6117 return result;
6118 }
6119
6121 }
6122
6123 private:
6124 IteratorType current;
6125 IteratorType end;
6126
6127 template <typename BaseInputAdapter, size_t T> friend struct wide_string_input_helper;
6128
6129 bool empty() const { return current == end; }
6130};
6131
6132template <typename BaseInputAdapter, size_t T> struct wide_string_input_helper;
6133
6134template <typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 4> {
6135 // UTF-32
6136 static void fill_buffer(BaseInputAdapter& input,
6137 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6138 size_t& utf8_bytes_index, size_t& utf8_bytes_filled) {
6139 utf8_bytes_index = 0;
6140
6141 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
6142 utf8_bytes[0] = std::char_traits<char>::eof();
6143 utf8_bytes_filled = 1;
6144 } else {
6145 // get the current character
6146 const auto wc = input.get_character();
6147
6148 // UTF-32 to UTF-8 encoding
6149 if (wc < 0x80) {
6150 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6151 utf8_bytes_filled = 1;
6152 } else if (wc <= 0x7FF) {
6153 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
6154 0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6155 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6156 0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6157 utf8_bytes_filled = 2;
6158 } else if (wc <= 0xFFFF) {
6159 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
6160 0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6161 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6162 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6163 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(
6164 0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6165 utf8_bytes_filled = 3;
6166 } else if (wc <= 0x10FFFF) {
6167 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
6168 0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6169 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6170 0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6171 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(
6172 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6173 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(
6174 0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6175 utf8_bytes_filled = 4;
6176 } else {
6177 // unknown character
6178 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6179 utf8_bytes_filled = 1;
6180 }
6181 }
6182 }
6183};
6184
6185template <typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 2> {
6186 // UTF-16
6187 static void fill_buffer(BaseInputAdapter& input,
6188 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6189 size_t& utf8_bytes_index, size_t& utf8_bytes_filled) {
6190 utf8_bytes_index = 0;
6191
6192 if (JSON_HEDLEY_UNLIKELY(input.empty())) {
6193 utf8_bytes[0] = std::char_traits<char>::eof();
6194 utf8_bytes_filled = 1;
6195 } else {
6196 // get the current character
6197 const auto wc = input.get_character();
6198
6199 // UTF-16 to UTF-8 encoding
6200 if (wc < 0x80) {
6201 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6202 utf8_bytes_filled = 1;
6203 } else if (wc <= 0x7FF) {
6204 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
6205 0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6206 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6207 0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6208 utf8_bytes_filled = 2;
6209 } else if (0xD800 > wc || wc >= 0xE000) {
6210 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(
6211 0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6212 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6213 0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6214 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(
6215 0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6216 utf8_bytes_filled = 3;
6217 } else {
6218 if (JSON_HEDLEY_UNLIKELY(!input.empty())) {
6219 const auto wc2 = static_cast<unsigned int>(input.get_character());
6220 const auto charcode =
6221 0x10000u +
6222 (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6223 utf8_bytes[0] =
6224 static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6225 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(
6226 0x80u | ((charcode >> 12u) & 0x3Fu));
6227 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(
6228 0x80u | ((charcode >> 6u) & 0x3Fu));
6229 utf8_bytes[3] =
6230 static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6231 utf8_bytes_filled = 4;
6232 } else {
6233 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6234 utf8_bytes_filled = 1;
6235 }
6236 }
6237 }
6238 }
6239};
6240
6241// Wraps another input adapter to convert wide character types into individual
6242// bytes.
6243template <typename BaseInputAdapter, typename WideCharType> class wide_string_input_adapter {
6244 public:
6245 using char_type = char;
6246
6247 wide_string_input_adapter(BaseInputAdapter base) : base_adapter(base) {}
6248
6249 typename std::char_traits<char>::int_type get_character() noexcept {
6250 // check if buffer needs to be filled
6251 if (utf8_bytes_index == utf8_bytes_filled) {
6252 fill_buffer<sizeof(WideCharType)>();
6253
6254 JSON_ASSERT(utf8_bytes_filled > 0);
6255 JSON_ASSERT(utf8_bytes_index == 0);
6256 }
6257
6258 // use buffer
6259 JSON_ASSERT(utf8_bytes_filled > 0);
6260 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6261 return utf8_bytes[utf8_bytes_index++];
6262 }
6263
6264 private:
6265 BaseInputAdapter base_adapter;
6266
6267 template <size_t T> void fill_buffer() {
6269 base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6270 }
6271
6273 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6274
6276 std::size_t utf8_bytes_index = 0;
6278 std::size_t utf8_bytes_filled = 0;
6279};
6280
6281template <typename IteratorType, typename Enable = void> struct iterator_input_adapter_factory {
6282 using iterator_type = IteratorType;
6283 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6284 using adapter_type = iterator_input_adapter<iterator_type>;
6285
6286 static adapter_type create(IteratorType first, IteratorType last) {
6287 return adapter_type(std::move(first), std::move(last));
6288 }
6289};
6290
6291template <typename T> struct is_iterator_of_multibyte {
6292 using value_type = typename std::iterator_traits<T>::value_type;
6293 enum { value = sizeof(value_type) > 1 };
6294};
6295
6296template <typename IteratorType>
6298 enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> {
6299 using iterator_type = IteratorType;
6300 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6301 using base_adapter_type = iterator_input_adapter<iterator_type>;
6303
6304 static adapter_type create(IteratorType first, IteratorType last) {
6305 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6306 }
6307};
6308
6309// General purpose iterator-based input
6310template <typename IteratorType>
6311typename iterator_input_adapter_factory<IteratorType>::adapter_type
6312input_adapter(IteratorType first, IteratorType last) {
6314 return factory_type::create(first, last);
6315}
6316
6317// Convenience shorthand from container to iterator
6318// Enables ADL on begin(container) and end(container)
6319// Encloses the using declarations in namespace for not to leak them to outside
6320// scope
6321
6322namespace container_input_adapter_factory_impl {
6323
6324using std::begin;
6325using std::end;
6326
6327template <typename ContainerType, typename Enable = void> struct container_input_adapter_factory {};
6328
6329template <typename ContainerType>
6331 ContainerType,
6332 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> {
6333 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()),
6334 end(std::declval<ContainerType>())));
6335
6336 static adapter_type create(const ContainerType& container) {
6337 return input_adapter(begin(container), end(container));
6338 }
6339};
6340
6341} // namespace container_input_adapter_factory_impl
6342
6343template <typename ContainerType>
6345 ContainerType>::adapter_type
6346input_adapter(const ContainerType& container) {
6348 ContainerType>::create(container);
6349}
6350
6351#ifndef JSON_NO_IO
6352// Special cases with fast paths
6353inline file_input_adapter input_adapter(std::FILE* file) {
6354 return file_input_adapter(file);
6355}
6356
6357inline input_stream_adapter input_adapter(std::istream& stream) {
6358 return input_stream_adapter(stream);
6359}
6360
6361inline input_stream_adapter input_adapter(std::istream&& stream) {
6362 return input_stream_adapter(stream);
6363}
6364#endif // JSON_NO_IO
6365
6366using contiguous_bytes_input_adapter =
6367 decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6368
6369// Null-delimited strings, and the like.
6370template <typename CharT,
6371 typename std::enable_if<
6372 std::is_pointer<CharT>::value && !std::is_array<CharT>::value &&
6373 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6374 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6375 int>::type = 0>
6376contiguous_bytes_input_adapter input_adapter(CharT b) {
6377 auto length = std::strlen(reinterpret_cast<const char*>(b));
6378 const auto* ptr = reinterpret_cast<const char*>(b);
6379 return input_adapter(ptr, ptr + length);
6380}
6381
6382template <typename T, std::size_t N>
6383auto input_adapter(T (&array)[N]) -> decltype(input_adapter(
6384 array,
6385 array +
6386 N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6387{
6388 return input_adapter(array, array + N);
6389}
6390
6391// This class only handles inputs of input_buffer_adapter type.
6392// It's required so that expressions like {ptr, len} can be implicitly cast
6393// to the correct adapter.
6394class span_input_adapter {
6395 public:
6396 template <typename CharT,
6397 typename std::enable_if<
6398 std::is_pointer<CharT>::value &&
6399 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6400 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6401 int>::type = 0>
6402 span_input_adapter(CharT b, std::size_t l)
6403 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6404
6405 template <class IteratorType,
6406 typename std::enable_if<
6407 std::is_same<typename iterator_traits<IteratorType>::iterator_category,
6408 std::random_access_iterator_tag>::value,
6409 int>::type = 0>
6410 span_input_adapter(IteratorType first, IteratorType last) : ia(input_adapter(first, last)) {}
6411
6412 contiguous_bytes_input_adapter&& get() {
6413 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6414 }
6415
6416 private:
6417 contiguous_bytes_input_adapter ia;
6418};
6419
6420} // namespace detail
6421NLOHMANN_JSON_NAMESPACE_END
6422
6423// #include <nlohmann/detail/input/json_sax.hpp>
6424// __ _____ _____ _____
6425// __| | __| | | | JSON for Modern C++
6426// | | |__ | | | | | | version 3.11.3
6427// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6428//
6429// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6430// SPDX-License-Identifier: MIT
6431
6432#include <cstddef>
6433#include <string> // string
6434#include <utility> // move
6435#include <vector> // vector
6436
6437// #include <nlohmann/detail/exceptions.hpp>
6438
6439// #include <nlohmann/detail/macro_scope.hpp>
6440
6441// #include <nlohmann/detail/string_concat.hpp>
6442
6443NLOHMANN_JSON_NAMESPACE_BEGIN
6444
6453template <typename BasicJsonType> struct json_sax {
6454 using number_integer_t = typename BasicJsonType::number_integer_t;
6455 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6456 using number_float_t = typename BasicJsonType::number_float_t;
6457 using string_t = typename BasicJsonType::string_t;
6458 using binary_t = typename BasicJsonType::binary_t;
6459
6464 virtual bool null() = 0;
6465
6471 virtual bool boolean(bool val) = 0;
6472
6478 virtual bool number_integer(number_integer_t val) = 0;
6479
6485 virtual bool number_unsigned(number_unsigned_t val) = 0;
6486
6493 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6494
6501 virtual bool string(string_t& val) = 0;
6502
6509 virtual bool binary(binary_t& val) = 0;
6510
6517 virtual bool start_object(std::size_t elements) = 0;
6518
6525 virtual bool key(string_t& val) = 0;
6526
6531 virtual bool end_object() = 0;
6532
6539 virtual bool start_array(std::size_t elements) = 0;
6540
6545 virtual bool end_array() = 0;
6546
6554 virtual bool parse_error(std::size_t position, const std::string& last_token,
6555 const detail::exception& ex) = 0;
6556
6557 json_sax() = default;
6558 json_sax(const json_sax&) = default;
6559 json_sax(json_sax&&) noexcept = default;
6560 json_sax& operator=(const json_sax&) = default;
6561 json_sax& operator=(json_sax&&) noexcept = default;
6562 virtual ~json_sax() = default;
6563};
6564
6565namespace detail {
6579template <typename BasicJsonType> class json_sax_dom_parser {
6580 public:
6581 using number_integer_t = typename BasicJsonType::number_integer_t;
6582 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6583 using number_float_t = typename BasicJsonType::number_float_t;
6584 using string_t = typename BasicJsonType::string_t;
6585 using binary_t = typename BasicJsonType::binary_t;
6586
6592 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6593 : root(r), allow_exceptions(allow_exceptions_) {}
6594
6595 // make class move-only
6598 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6599 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6601 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6602 ~json_sax_dom_parser() = default;
6603
6604 bool null() {
6605 handle_value(nullptr);
6606 return true;
6607 }
6608
6609 bool boolean(bool val) {
6610 handle_value(val);
6611 return true;
6612 }
6613
6614 bool number_integer(number_integer_t val) {
6615 handle_value(val);
6616 return true;
6617 }
6618
6619 bool number_unsigned(number_unsigned_t val) {
6620 handle_value(val);
6621 return true;
6622 }
6623
6624 bool number_float(number_float_t val, const string_t& /*unused*/) {
6625 handle_value(val);
6626 return true;
6627 }
6628
6629 bool string(string_t& val) {
6630 handle_value(val);
6631 return true;
6632 }
6633
6634 bool binary(binary_t& val) {
6635 handle_value(std::move(val));
6636 return true;
6637 }
6638
6639 bool start_object(std::size_t len) {
6640 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6641
6642 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) &&
6643 len > ref_stack.back()->max_size())) {
6644 JSON_THROW(out_of_range::create(
6645 408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6646 }
6647
6648 return true;
6649 }
6650
6651 bool key(string_t& val) {
6652 JSON_ASSERT(!ref_stack.empty());
6653 JSON_ASSERT(ref_stack.back()->is_object());
6654
6655 // add null at given key and store the reference for later
6656 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6657 return true;
6658 }
6659
6660 bool end_object() {
6661 JSON_ASSERT(!ref_stack.empty());
6662 JSON_ASSERT(ref_stack.back()->is_object());
6663
6664 ref_stack.back()->set_parents();
6665 ref_stack.pop_back();
6666 return true;
6667 }
6668
6669 bool start_array(std::size_t len) {
6670 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6671
6672 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) &&
6673 len > ref_stack.back()->max_size())) {
6674 JSON_THROW(out_of_range::create(
6675 408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6676 }
6677
6678 return true;
6679 }
6680
6681 bool end_array() {
6682 JSON_ASSERT(!ref_stack.empty());
6683 JSON_ASSERT(ref_stack.back()->is_array());
6684
6685 ref_stack.back()->set_parents();
6686 ref_stack.pop_back();
6687 return true;
6688 }
6689
6690 template <class Exception>
6691 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex) {
6692 errored = true;
6693 static_cast<void>(ex);
6694 if (allow_exceptions) {
6695 JSON_THROW(ex);
6696 }
6697 return false;
6698 }
6699
6700 constexpr bool is_errored() const { return errored; }
6701
6702 private:
6709 template <typename Value> JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType* handle_value(Value&& v) {
6710 if (ref_stack.empty()) {
6711 root = BasicJsonType(std::forward<Value>(v));
6712 return &root;
6713 }
6714
6715 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6716
6717 if (ref_stack.back()->is_array()) {
6718 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6719 return &(ref_stack.back()->m_data.m_value.array->back());
6720 }
6721
6722 JSON_ASSERT(ref_stack.back()->is_object());
6723 JSON_ASSERT(object_element);
6724 *object_element = BasicJsonType(std::forward<Value>(v));
6725 return object_element;
6726 }
6727
6729 BasicJsonType& root;
6731 std::vector<BasicJsonType*> ref_stack{};
6733 BasicJsonType* object_element = nullptr;
6735 bool errored = false;
6737 const bool allow_exceptions = true;
6738};
6739
6740template <typename BasicJsonType> class json_sax_dom_callback_parser {
6741 public:
6742 using number_integer_t = typename BasicJsonType::number_integer_t;
6743 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6744 using number_float_t = typename BasicJsonType::number_float_t;
6745 using string_t = typename BasicJsonType::string_t;
6746 using binary_t = typename BasicJsonType::binary_t;
6747 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6748 using parse_event_t = typename BasicJsonType::parse_event_t;
6749
6750 json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb,
6751 const bool allow_exceptions_ = true)
6752 : root(r), callback(cb), allow_exceptions(allow_exceptions_) {
6753 keep_stack.push_back(true);
6754 }
6755
6756 // make class move-only
6757 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6758 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) =
6759 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6760 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6761 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) =
6762 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6763 ~json_sax_dom_callback_parser() = default;
6764
6765 bool null() {
6766 handle_value(nullptr);
6767 return true;
6768 }
6769
6770 bool boolean(bool val) {
6771 handle_value(val);
6772 return true;
6773 }
6774
6775 bool number_integer(number_integer_t val) {
6776 handle_value(val);
6777 return true;
6778 }
6779
6780 bool number_unsigned(number_unsigned_t val) {
6781 handle_value(val);
6782 return true;
6783 }
6784
6785 bool number_float(number_float_t val, const string_t& /*unused*/) {
6786 handle_value(val);
6787 return true;
6788 }
6789
6790 bool string(string_t& val) {
6791 handle_value(val);
6792 return true;
6793 }
6794
6795 bool binary(binary_t& val) {
6796 handle_value(std::move(val));
6797 return true;
6798 }
6799
6800 bool start_object(std::size_t len) {
6801 // check callback for object start
6802 const bool keep =
6803 callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6804 keep_stack.push_back(keep);
6805
6806 auto val = handle_value(BasicJsonType::value_t::object, true);
6807 ref_stack.push_back(val.second);
6808
6809 // check object limit
6810 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) &&
6811 len > ref_stack.back()->max_size())) {
6812 JSON_THROW(out_of_range::create(
6813 408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6814 }
6815
6816 return true;
6817 }
6818
6819 bool key(string_t& val) {
6820 BasicJsonType k = BasicJsonType(val);
6821
6822 // check callback for key
6823 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
6824 key_keep_stack.push_back(keep);
6825
6826 // add discarded value at given key and store the reference for later
6827 if (keep && ref_stack.back()) {
6828 object_element =
6829 &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
6830 }
6831
6832 return true;
6833 }
6834
6835 bool end_object() {
6836 if (ref_stack.back()) {
6837 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end,
6838 *ref_stack.back())) {
6839 // discard object
6840 *ref_stack.back() = discarded;
6841 } else {
6842 ref_stack.back()->set_parents();
6843 }
6844 }
6845
6846 JSON_ASSERT(!ref_stack.empty());
6847 JSON_ASSERT(!keep_stack.empty());
6848 ref_stack.pop_back();
6849 keep_stack.pop_back();
6850
6851 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) {
6852 // remove discarded value
6853 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) {
6854 if (it->is_discarded()) {
6855 ref_stack.back()->erase(it);
6856 break;
6857 }
6858 }
6859 }
6860
6861 return true;
6862 }
6863
6864 bool start_array(std::size_t len) {
6865 const bool keep =
6866 callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
6867 keep_stack.push_back(keep);
6868
6869 auto val = handle_value(BasicJsonType::value_t::array, true);
6870 ref_stack.push_back(val.second);
6871
6872 // check array limit
6873 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) &&
6874 len > ref_stack.back()->max_size())) {
6875 JSON_THROW(out_of_range::create(
6876 408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6877 }
6878
6879 return true;
6880 }
6881
6882 bool end_array() {
6883 bool keep = true;
6884
6885 if (ref_stack.back()) {
6886 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end,
6887 *ref_stack.back());
6888 if (keep) {
6889 ref_stack.back()->set_parents();
6890 } else {
6891 // discard array
6892 *ref_stack.back() = discarded;
6893 }
6894 }
6895
6896 JSON_ASSERT(!ref_stack.empty());
6897 JSON_ASSERT(!keep_stack.empty());
6898 ref_stack.pop_back();
6899 keep_stack.pop_back();
6900
6901 // remove discarded value
6902 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) {
6903 ref_stack.back()->m_data.m_value.array->pop_back();
6904 }
6905
6906 return true;
6907 }
6908
6909 template <class Exception>
6910 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex) {
6911 errored = true;
6912 static_cast<void>(ex);
6913 if (allow_exceptions) {
6914 JSON_THROW(ex);
6915 }
6916 return false;
6917 }
6918
6919 constexpr bool is_errored() const { return errored; }
6920
6921 private:
6937 template <typename Value>
6938 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) {
6939 JSON_ASSERT(!keep_stack.empty());
6940
6941 // do not handle this value if we know it would be added to a discarded
6942 // container
6943 if (!keep_stack.back()) {
6944 return {false, nullptr};
6945 }
6946
6947 // create value
6948 auto value = BasicJsonType(std::forward<Value>(v));
6949
6950 // check callback
6951 const bool keep = skip_callback ||
6952 callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
6953
6954 // do not handle this value if we just learnt it shall be discarded
6955 if (!keep) {
6956 return {false, nullptr};
6957 }
6958
6959 if (ref_stack.empty()) {
6960 root = std::move(value);
6961 return {true, &root};
6962 }
6963
6964 // skip this value if we already decided to skip the parent
6965 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
6966 if (!ref_stack.back()) {
6967 return {false, nullptr};
6968 }
6969
6970 // we now only expect arrays and objects
6971 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6972
6973 // array
6974 if (ref_stack.back()->is_array()) {
6975 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
6976 return {true, &(ref_stack.back()->m_data.m_value.array->back())};
6977 }
6978
6979 // object
6980 JSON_ASSERT(ref_stack.back()->is_object());
6981 // check if we should store an element for the current key
6982 JSON_ASSERT(!key_keep_stack.empty());
6983 const bool store_element = key_keep_stack.back();
6984 key_keep_stack.pop_back();
6985
6986 if (!store_element) {
6987 return {false, nullptr};
6988 }
6989
6990 JSON_ASSERT(object_element);
6991 *object_element = std::move(value);
6992 return {true, object_element};
6993 }
6994
6996 BasicJsonType& root;
6998 std::vector<BasicJsonType*> ref_stack{};
7000 std::vector<bool> keep_stack{}; // NOLINT(readability-redundant-member-init)
7002 std::vector<bool> key_keep_stack{}; // NOLINT(readability-redundant-member-init)
7004 BasicJsonType* object_element = nullptr;
7006 bool errored = false;
7008 const parser_callback_t callback = nullptr;
7010 const bool allow_exceptions = true;
7012 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7013};
7014
7015template <typename BasicJsonType> class json_sax_acceptor {
7016 public:
7017 using number_integer_t = typename BasicJsonType::number_integer_t;
7018 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7019 using number_float_t = typename BasicJsonType::number_float_t;
7020 using string_t = typename BasicJsonType::string_t;
7021 using binary_t = typename BasicJsonType::binary_t;
7022
7023 bool null() { return true; }
7024
7025 bool boolean(bool /*unused*/) { return true; }
7026
7027 bool number_integer(number_integer_t /*unused*/) { return true; }
7028
7029 bool number_unsigned(number_unsigned_t /*unused*/) { return true; }
7030
7031 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) { return true; }
7032
7033 bool string(string_t& /*unused*/) { return true; }
7034
7035 bool binary(binary_t& /*unused*/) { return true; }
7036
7037 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) { return true; }
7038
7039 bool key(string_t& /*unused*/) { return true; }
7040
7041 bool end_object() { return true; }
7042
7043 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) { return true; }
7044
7045 bool end_array() { return true; }
7046
7047 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7048 const detail::exception& /*unused*/) {
7049 return false;
7050 }
7051};
7052
7053} // namespace detail
7054NLOHMANN_JSON_NAMESPACE_END
7055
7056// #include <nlohmann/detail/input/lexer.hpp>
7057// __ _____ _____ _____
7058// __| | __| | | | JSON for Modern C++
7059// | | |__ | | | | | | version 3.11.3
7060// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7061//
7062// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7063// SPDX-License-Identifier: MIT
7064
7065#include <array> // array
7066#include <clocale> // localeconv
7067#include <cstddef> // size_t
7068#include <cstdio> // snprintf
7069#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7070#include <initializer_list> // initializer_list
7071#include <string> // char_traits, string
7072#include <utility> // move
7073#include <vector> // vector
7074
7075// #include <nlohmann/detail/input/input_adapters.hpp>
7076
7077// #include <nlohmann/detail/input/position_t.hpp>
7078
7079// #include <nlohmann/detail/macro_scope.hpp>
7080
7081// #include <nlohmann/detail/meta/type_traits.hpp>
7082
7083NLOHMANN_JSON_NAMESPACE_BEGIN
7084namespace detail {
7085
7087// lexer //
7089
7090template <typename BasicJsonType> class lexer_base {
7091 public:
7116
7118 JSON_HEDLEY_RETURNS_NON_NULL
7119 JSON_HEDLEY_CONST
7120 static const char* token_type_name(const token_type t) noexcept {
7121 switch (t) {
7123 return "<uninitialized>";
7125 return "true literal";
7127 return "false literal";
7129 return "null literal";
7131 return "string literal";
7135 return "number literal";
7137 return "'['";
7139 return "'{'";
7141 return "']'";
7143 return "'}'";
7145 return "':'";
7147 return "','";
7149 return "<parse error>";
7151 return "end of input";
7153 return "'[', '{', or a literal";
7154 // LCOV_EXCL_START
7155 default: // catch non-enum values
7156 return "unknown token";
7157 // LCOV_EXCL_STOP
7158 }
7159 }
7160};
7161
7166template <typename BasicJsonType, typename InputAdapterType>
7167class lexer : public lexer_base<BasicJsonType> {
7168 using number_integer_t = typename BasicJsonType::number_integer_t;
7169 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7170 using number_float_t = typename BasicJsonType::number_float_t;
7171 using string_t = typename BasicJsonType::string_t;
7172 using char_type = typename InputAdapterType::char_type;
7173 using char_int_type = typename char_traits<char_type>::int_type;
7174
7175 public:
7176 using token_type = typename lexer_base<BasicJsonType>::token_type;
7177
7178 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7179 : ia(std::move(adapter)), ignore_comments(ignore_comments_),
7180 decimal_point_char(static_cast<char_int_type>(get_decimal_point())) {}
7181
7182 // delete because of pointer members
7183 lexer(const lexer&) = delete;
7184 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7185 lexer& operator=(lexer&) = delete;
7186 lexer& operator=(lexer&&) =
7187 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7188 ~lexer() = default;
7189
7190 private:
7192 // locales
7194
7196 JSON_HEDLEY_PURE
7197 static char get_decimal_point() noexcept {
7198 const auto* loc = localeconv();
7199 JSON_ASSERT(loc != nullptr);
7200 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7201 }
7202
7204 // scan functions
7206
7222 int get_codepoint() {
7223 // this function only makes sense after reading `\u`
7224 JSON_ASSERT(current == 'u');
7225 int codepoint = 0;
7226
7227 const auto factors = {12u, 8u, 4u, 0u};
7228 for (const auto factor : factors) {
7229 get();
7230
7231 if (current >= '0' && current <= '9') {
7232 codepoint +=
7233 static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7234 } else if (current >= 'A' && current <= 'F') {
7235 codepoint +=
7236 static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7237 } else if (current >= 'a' && current <= 'f') {
7238 codepoint +=
7239 static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7240 } else {
7241 return -1;
7242 }
7243 }
7244
7245 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7246 return codepoint;
7247 }
7248
7264 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) {
7265 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7266 add(current);
7267
7268 for (auto range = ranges.begin(); range != ranges.end(); ++range) {
7269 get();
7270 if (JSON_HEDLEY_LIKELY(*range <= current &&
7271 current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7272 {
7273 add(current);
7274 } else {
7275 error_message = "invalid string: ill-formed UTF-8 byte";
7276 return false;
7277 }
7278 }
7279
7280 return true;
7281 }
7282
7298 token_type scan_string() {
7299 // reset token_buffer (ignore opening quote)
7300 reset();
7301
7302 // we entered the function by reading an open quote
7303 JSON_ASSERT(current == '\"');
7304
7305 while (true) {
7306 // get next character
7307 switch (get()) {
7308 // end of file while parsing string
7310 error_message = "invalid string: missing closing quote";
7311 return token_type::parse_error;
7312 }
7313
7314 // closing quote
7315 case '\"': {
7316 return token_type::value_string;
7317 }
7318
7319 // escapes
7320 case '\\': {
7321 switch (get()) {
7322 // quotation mark
7323 case '\"':
7324 add('\"');
7325 break;
7326 // reverse solidus
7327 case '\\':
7328 add('\\');
7329 break;
7330 // solidus
7331 case '/':
7332 add('/');
7333 break;
7334 // backspace
7335 case 'b':
7336 add('\b');
7337 break;
7338 // form feed
7339 case 'f':
7340 add('\f');
7341 break;
7342 // line feed
7343 case 'n':
7344 add('\n');
7345 break;
7346 // carriage return
7347 case 'r':
7348 add('\r');
7349 break;
7350 // tab
7351 case 't':
7352 add('\t');
7353 break;
7354
7355 // unicode escapes
7356 case 'u': {
7357 const int codepoint1 = get_codepoint();
7358 int codepoint = codepoint1; // start with codepoint1
7359
7360 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) {
7361 error_message =
7362 "invalid string: '\\u' must be followed by 4 hex digits";
7363 return token_type::parse_error;
7364 }
7365
7366 // check if code point is a high surrogate
7367 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) {
7368 // expect next \uxxxx entry
7369 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) {
7370 const int codepoint2 = get_codepoint();
7371
7372 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) {
7373 error_message = "invalid string: '\\u' must be followed by "
7374 "4 hex digits";
7375 return token_type::parse_error;
7376 }
7377
7378 // check if codepoint2 is a low surrogate
7379 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 &&
7380 codepoint2 <= 0xDFFF)) {
7381 // overwrite codepoint
7382 codepoint = static_cast<int>(
7383 // high surrogate occupies the most significant 22 bits
7384 (static_cast<unsigned int>(codepoint1) << 10u)
7385 // low surrogate occupies the least significant 15 bits
7386 + static_cast<unsigned int>(codepoint2)
7387 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7388 // in the result, so we have to subtract with:
7389 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7390 - 0x35FDC00u);
7391 } else {
7392 error_message =
7393 "invalid string: surrogate U+D800..U+DBFF must "
7394 "be followed by U+DC00..U+DFFF";
7395 return token_type::parse_error;
7396 }
7397 } else {
7398 error_message = "invalid string: surrogate U+D800..U+DBFF must "
7399 "be followed by U+DC00..U+DFFF";
7400 return token_type::parse_error;
7401 }
7402 } else {
7403 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 &&
7404 codepoint1 <= 0xDFFF)) {
7405 error_message = "invalid string: surrogate U+DC00..U+DFFF must "
7406 "follow U+D800..U+DBFF";
7407 return token_type::parse_error;
7408 }
7409 }
7410
7411 // result of the above calculation yields a proper codepoint
7412 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7413
7414 // translate codepoint into bytes
7415 if (codepoint < 0x80) {
7416 // 1-byte characters: 0xxxxxxx (ASCII)
7417 add(static_cast<char_int_type>(codepoint));
7418 } else if (codepoint <= 0x7FF) {
7419 // 2-byte characters: 110xxxxx 10xxxxxx
7420 add(static_cast<char_int_type>(
7421 0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7422 add(static_cast<char_int_type>(
7423 0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7424 } else if (codepoint <= 0xFFFF) {
7425 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7426 add(static_cast<char_int_type>(
7427 0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7428 add(static_cast<char_int_type>(
7429 0x80u |
7430 ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7431 add(static_cast<char_int_type>(
7432 0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7433 } else {
7434 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7435 add(static_cast<char_int_type>(
7436 0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7437 add(static_cast<char_int_type>(
7438 0x80u |
7439 ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7440 add(static_cast<char_int_type>(
7441 0x80u |
7442 ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7443 add(static_cast<char_int_type>(
7444 0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7445 }
7446
7447 break;
7448 }
7449
7450 // other characters after escape
7451 default:
7452 error_message = "invalid string: forbidden character after backslash";
7453 return token_type::parse_error;
7454 }
7455
7456 break;
7457 }
7458
7459 // invalid control characters
7460 case 0x00: {
7461 error_message = "invalid string: control character U+0000 (NUL) must "
7462 "be escaped to \\u0000";
7463 return token_type::parse_error;
7464 }
7465
7466 case 0x01: {
7467 error_message = "invalid string: control character U+0001 (SOH) must "
7468 "be escaped to \\u0001";
7469 return token_type::parse_error;
7470 }
7471
7472 case 0x02: {
7473 error_message = "invalid string: control character U+0002 (STX) must "
7474 "be escaped to \\u0002";
7475 return token_type::parse_error;
7476 }
7477
7478 case 0x03: {
7479 error_message = "invalid string: control character U+0003 (ETX) must "
7480 "be escaped to \\u0003";
7481 return token_type::parse_error;
7482 }
7483
7484 case 0x04: {
7485 error_message = "invalid string: control character U+0004 (EOT) must "
7486 "be escaped to \\u0004";
7487 return token_type::parse_error;
7488 }
7489
7490 case 0x05: {
7491 error_message = "invalid string: control character U+0005 (ENQ) must "
7492 "be escaped to \\u0005";
7493 return token_type::parse_error;
7494 }
7495
7496 case 0x06: {
7497 error_message = "invalid string: control character U+0006 (ACK) must "
7498 "be escaped to \\u0006";
7499 return token_type::parse_error;
7500 }
7501
7502 case 0x07: {
7503 error_message = "invalid string: control character U+0007 (BEL) must "
7504 "be escaped to \\u0007";
7505 return token_type::parse_error;
7506 }
7507
7508 case 0x08: {
7509 error_message = "invalid string: control character U+0008 (BS) must be "
7510 "escaped to \\u0008 or \\b";
7511 return token_type::parse_error;
7512 }
7513
7514 case 0x09: {
7515 error_message = "invalid string: control character U+0009 (HT) must be "
7516 "escaped to \\u0009 or \\t";
7517 return token_type::parse_error;
7518 }
7519
7520 case 0x0A: {
7521 error_message = "invalid string: control character U+000A (LF) must be "
7522 "escaped to \\u000A or \\n";
7523 return token_type::parse_error;
7524 }
7525
7526 case 0x0B: {
7527 error_message = "invalid string: control character U+000B (VT) must be "
7528 "escaped to \\u000B";
7529 return token_type::parse_error;
7530 }
7531
7532 case 0x0C: {
7533 error_message = "invalid string: control character U+000C (FF) must be "
7534 "escaped to \\u000C or \\f";
7535 return token_type::parse_error;
7536 }
7537
7538 case 0x0D: {
7539 error_message = "invalid string: control character U+000D (CR) must be "
7540 "escaped to \\u000D or \\r";
7541 return token_type::parse_error;
7542 }
7543
7544 case 0x0E: {
7545 error_message = "invalid string: control character U+000E (SO) must be "
7546 "escaped to \\u000E";
7547 return token_type::parse_error;
7548 }
7549
7550 case 0x0F: {
7551 error_message = "invalid string: control character U+000F (SI) must be "
7552 "escaped to \\u000F";
7553 return token_type::parse_error;
7554 }
7555
7556 case 0x10: {
7557 error_message = "invalid string: control character U+0010 (DLE) must "
7558 "be escaped to \\u0010";
7559 return token_type::parse_error;
7560 }
7561
7562 case 0x11: {
7563 error_message = "invalid string: control character U+0011 (DC1) must "
7564 "be escaped to \\u0011";
7565 return token_type::parse_error;
7566 }
7567
7568 case 0x12: {
7569 error_message = "invalid string: control character U+0012 (DC2) must "
7570 "be escaped to \\u0012";
7571 return token_type::parse_error;
7572 }
7573
7574 case 0x13: {
7575 error_message = "invalid string: control character U+0013 (DC3) must "
7576 "be escaped to \\u0013";
7577 return token_type::parse_error;
7578 }
7579
7580 case 0x14: {
7581 error_message = "invalid string: control character U+0014 (DC4) must "
7582 "be escaped to \\u0014";
7583 return token_type::parse_error;
7584 }
7585
7586 case 0x15: {
7587 error_message = "invalid string: control character U+0015 (NAK) must "
7588 "be escaped to \\u0015";
7589 return token_type::parse_error;
7590 }
7591
7592 case 0x16: {
7593 error_message = "invalid string: control character U+0016 (SYN) must "
7594 "be escaped to \\u0016";
7595 return token_type::parse_error;
7596 }
7597
7598 case 0x17: {
7599 error_message = "invalid string: control character U+0017 (ETB) must "
7600 "be escaped to \\u0017";
7601 return token_type::parse_error;
7602 }
7603
7604 case 0x18: {
7605 error_message = "invalid string: control character U+0018 (CAN) must "
7606 "be escaped to \\u0018";
7607 return token_type::parse_error;
7608 }
7609
7610 case 0x19: {
7611 error_message = "invalid string: control character U+0019 (EM) must be "
7612 "escaped to \\u0019";
7613 return token_type::parse_error;
7614 }
7615
7616 case 0x1A: {
7617 error_message = "invalid string: control character U+001A (SUB) must "
7618 "be escaped to \\u001A";
7619 return token_type::parse_error;
7620 }
7621
7622 case 0x1B: {
7623 error_message = "invalid string: control character U+001B (ESC) must "
7624 "be escaped to \\u001B";
7625 return token_type::parse_error;
7626 }
7627
7628 case 0x1C: {
7629 error_message = "invalid string: control character U+001C (FS) must be "
7630 "escaped to \\u001C";
7631 return token_type::parse_error;
7632 }
7633
7634 case 0x1D: {
7635 error_message = "invalid string: control character U+001D (GS) must be "
7636 "escaped to \\u001D";
7637 return token_type::parse_error;
7638 }
7639
7640 case 0x1E: {
7641 error_message = "invalid string: control character U+001E (RS) must be "
7642 "escaped to \\u001E";
7643 return token_type::parse_error;
7644 }
7645
7646 case 0x1F: {
7647 error_message = "invalid string: control character U+001F (US) must be "
7648 "escaped to \\u001F";
7649 return token_type::parse_error;
7650 }
7651
7652 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7653 case 0x20:
7654 case 0x21:
7655 case 0x23:
7656 case 0x24:
7657 case 0x25:
7658 case 0x26:
7659 case 0x27:
7660 case 0x28:
7661 case 0x29:
7662 case 0x2A:
7663 case 0x2B:
7664 case 0x2C:
7665 case 0x2D:
7666 case 0x2E:
7667 case 0x2F:
7668 case 0x30:
7669 case 0x31:
7670 case 0x32:
7671 case 0x33:
7672 case 0x34:
7673 case 0x35:
7674 case 0x36:
7675 case 0x37:
7676 case 0x38:
7677 case 0x39:
7678 case 0x3A:
7679 case 0x3B:
7680 case 0x3C:
7681 case 0x3D:
7682 case 0x3E:
7683 case 0x3F:
7684 case 0x40:
7685 case 0x41:
7686 case 0x42:
7687 case 0x43:
7688 case 0x44:
7689 case 0x45:
7690 case 0x46:
7691 case 0x47:
7692 case 0x48:
7693 case 0x49:
7694 case 0x4A:
7695 case 0x4B:
7696 case 0x4C:
7697 case 0x4D:
7698 case 0x4E:
7699 case 0x4F:
7700 case 0x50:
7701 case 0x51:
7702 case 0x52:
7703 case 0x53:
7704 case 0x54:
7705 case 0x55:
7706 case 0x56:
7707 case 0x57:
7708 case 0x58:
7709 case 0x59:
7710 case 0x5A:
7711 case 0x5B:
7712 case 0x5D:
7713 case 0x5E:
7714 case 0x5F:
7715 case 0x60:
7716 case 0x61:
7717 case 0x62:
7718 case 0x63:
7719 case 0x64:
7720 case 0x65:
7721 case 0x66:
7722 case 0x67:
7723 case 0x68:
7724 case 0x69:
7725 case 0x6A:
7726 case 0x6B:
7727 case 0x6C:
7728 case 0x6D:
7729 case 0x6E:
7730 case 0x6F:
7731 case 0x70:
7732 case 0x71:
7733 case 0x72:
7734 case 0x73:
7735 case 0x74:
7736 case 0x75:
7737 case 0x76:
7738 case 0x77:
7739 case 0x78:
7740 case 0x79:
7741 case 0x7A:
7742 case 0x7B:
7743 case 0x7C:
7744 case 0x7D:
7745 case 0x7E:
7746 case 0x7F: {
7747 add(current);
7748 break;
7749 }
7750
7751 // U+0080..U+07FF: bytes C2..DF 80..BF
7752 case 0xC2:
7753 case 0xC3:
7754 case 0xC4:
7755 case 0xC5:
7756 case 0xC6:
7757 case 0xC7:
7758 case 0xC8:
7759 case 0xC9:
7760 case 0xCA:
7761 case 0xCB:
7762 case 0xCC:
7763 case 0xCD:
7764 case 0xCE:
7765 case 0xCF:
7766 case 0xD0:
7767 case 0xD1:
7768 case 0xD2:
7769 case 0xD3:
7770 case 0xD4:
7771 case 0xD5:
7772 case 0xD6:
7773 case 0xD7:
7774 case 0xD8:
7775 case 0xD9:
7776 case 0xDA:
7777 case 0xDB:
7778 case 0xDC:
7779 case 0xDD:
7780 case 0xDE:
7781 case 0xDF: {
7782 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) {
7783 return token_type::parse_error;
7784 }
7785 break;
7786 }
7787
7788 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7789 case 0xE0: {
7790 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) {
7791 return token_type::parse_error;
7792 }
7793 break;
7794 }
7795
7796 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7797 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7798 case 0xE1:
7799 case 0xE2:
7800 case 0xE3:
7801 case 0xE4:
7802 case 0xE5:
7803 case 0xE6:
7804 case 0xE7:
7805 case 0xE8:
7806 case 0xE9:
7807 case 0xEA:
7808 case 0xEB:
7809 case 0xEC:
7810 case 0xEE:
7811 case 0xEF: {
7812 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) {
7813 return token_type::parse_error;
7814 }
7815 break;
7816 }
7817
7818 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7819 case 0xED: {
7820 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) {
7821 return token_type::parse_error;
7822 }
7823 break;
7824 }
7825
7826 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7827 case 0xF0: {
7828 if (JSON_HEDLEY_UNLIKELY(
7829 !(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) {
7830 return token_type::parse_error;
7831 }
7832 break;
7833 }
7834
7835 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7836 case 0xF1:
7837 case 0xF2:
7838 case 0xF3: {
7839 if (JSON_HEDLEY_UNLIKELY(
7840 !(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) {
7841 return token_type::parse_error;
7842 }
7843 break;
7844 }
7845
7846 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7847 case 0xF4: {
7848 if (JSON_HEDLEY_UNLIKELY(
7849 !(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) {
7850 return token_type::parse_error;
7851 }
7852 break;
7853 }
7854
7855 // remaining bytes (80..C1 and F5..FF) are ill-formed
7856 default: {
7857 error_message = "invalid string: ill-formed UTF-8 byte";
7858 return token_type::parse_error;
7859 }
7860 }
7861 }
7862 }
7863
7868 bool scan_comment() {
7869 switch (get()) {
7870 // single-line comments skip input until a newline or EOF is read
7871 case '/': {
7872 while (true) {
7873 switch (get()) {
7874 case '\n':
7875 case '\r':
7877 case '\0':
7878 return true;
7879
7880 default:
7881 break;
7882 }
7883 }
7884 }
7885
7886 // multi-line comments skip input until */ is read
7887 case '*': {
7888 while (true) {
7889 switch (get()) {
7891 case '\0': {
7892 error_message = "invalid comment; missing closing '*/'";
7893 return false;
7894 }
7895
7896 case '*': {
7897 switch (get()) {
7898 case '/':
7899 return true;
7900
7901 default: {
7902 unget();
7903 continue;
7904 }
7905 }
7906 }
7907
7908 default:
7909 continue;
7910 }
7911 }
7912 }
7913
7914 // unexpected character after reading '/'
7915 default: {
7916 error_message = "invalid comment; expecting '/' or '*' after '/'";
7917 return false;
7918 }
7919 }
7920 }
7921
7922 JSON_HEDLEY_NON_NULL(2)
7923 static void strtof(float& f, const char* str, char** endptr) noexcept {
7924 f = std::strtof(str, endptr);
7925 }
7926
7927 JSON_HEDLEY_NON_NULL(2)
7928 static void strtof(double& f, const char* str, char** endptr) noexcept {
7929 f = std::strtod(str, endptr);
7930 }
7931
7932 JSON_HEDLEY_NON_NULL(2)
7933 static void strtof(long double& f, const char* str, char** endptr) noexcept {
7934 f = std::strtold(str, endptr);
7935 }
7936
7979 token_type scan_number() // lgtm [cpp/use-of-goto]
7980 {
7981 // reset token_buffer to store the number's bytes
7982 reset();
7983
7984 // the type of the parsed number; initially set to unsigned; will be
7985 // changed if minus sign, decimal point or exponent is read
7986 token_type number_type = token_type::value_unsigned;
7987
7988 // state (init): we just found out we need to scan a number
7989 switch (current) {
7990 case '-': {
7991 add(current);
7992 goto scan_number_minus;
7993 }
7994
7995 case '0': {
7996 add(current);
7997 goto scan_number_zero;
7998 }
7999
8000 case '1':
8001 case '2':
8002 case '3':
8003 case '4':
8004 case '5':
8005 case '6':
8006 case '7':
8007 case '8':
8008 case '9': {
8009 add(current);
8010 goto scan_number_any1;
8011 }
8012
8013 // all other characters are rejected outside scan_number()
8014 default: // LCOV_EXCL_LINE
8015 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
8016 // LCOV_EXCL_LINE
8017 }
8018
8019 scan_number_minus:
8020 // state: we just parsed a leading minus sign
8021 number_type = token_type::value_integer;
8022 switch (get()) {
8023 case '0': {
8024 add(current);
8025 goto scan_number_zero;
8026 }
8027
8028 case '1':
8029 case '2':
8030 case '3':
8031 case '4':
8032 case '5':
8033 case '6':
8034 case '7':
8035 case '8':
8036 case '9': {
8037 add(current);
8038 goto scan_number_any1;
8039 }
8040
8041 default: {
8042 error_message = "invalid number; expected digit after '-'";
8043 return token_type::parse_error;
8044 }
8045 }
8046
8047 scan_number_zero:
8048 // state: we just parse a zero (maybe with a leading minus sign)
8049 switch (get()) {
8050 case '.': {
8051 add(decimal_point_char);
8052 goto scan_number_decimal1;
8053 }
8054
8055 case 'e':
8056 case 'E': {
8057 add(current);
8058 goto scan_number_exponent;
8059 }
8060
8061 default:
8062 goto scan_number_done;
8063 }
8064
8065 scan_number_any1:
8066 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8067 switch (get()) {
8068 case '0':
8069 case '1':
8070 case '2':
8071 case '3':
8072 case '4':
8073 case '5':
8074 case '6':
8075 case '7':
8076 case '8':
8077 case '9': {
8078 add(current);
8079 goto scan_number_any1;
8080 }
8081
8082 case '.': {
8083 add(decimal_point_char);
8084 goto scan_number_decimal1;
8085 }
8086
8087 case 'e':
8088 case 'E': {
8089 add(current);
8090 goto scan_number_exponent;
8091 }
8092
8093 default:
8094 goto scan_number_done;
8095 }
8096
8097 scan_number_decimal1:
8098 // state: we just parsed a decimal point
8099 number_type = token_type::value_float;
8100 switch (get()) {
8101 case '0':
8102 case '1':
8103 case '2':
8104 case '3':
8105 case '4':
8106 case '5':
8107 case '6':
8108 case '7':
8109 case '8':
8110 case '9': {
8111 add(current);
8112 goto scan_number_decimal2;
8113 }
8114
8115 default: {
8116 error_message = "invalid number; expected digit after '.'";
8117 return token_type::parse_error;
8118 }
8119 }
8120
8121 scan_number_decimal2:
8122 // we just parsed at least one number after a decimal point
8123 switch (get()) {
8124 case '0':
8125 case '1':
8126 case '2':
8127 case '3':
8128 case '4':
8129 case '5':
8130 case '6':
8131 case '7':
8132 case '8':
8133 case '9': {
8134 add(current);
8135 goto scan_number_decimal2;
8136 }
8137
8138 case 'e':
8139 case 'E': {
8140 add(current);
8141 goto scan_number_exponent;
8142 }
8143
8144 default:
8145 goto scan_number_done;
8146 }
8147
8148 scan_number_exponent:
8149 // we just parsed an exponent
8150 number_type = token_type::value_float;
8151 switch (get()) {
8152 case '+':
8153 case '-': {
8154 add(current);
8155 goto scan_number_sign;
8156 }
8157
8158 case '0':
8159 case '1':
8160 case '2':
8161 case '3':
8162 case '4':
8163 case '5':
8164 case '6':
8165 case '7':
8166 case '8':
8167 case '9': {
8168 add(current);
8169 goto scan_number_any2;
8170 }
8171
8172 default: {
8173 error_message = "invalid number; expected '+', '-', or digit after exponent";
8174 return token_type::parse_error;
8175 }
8176 }
8177
8178 scan_number_sign:
8179 // we just parsed an exponent sign
8180 switch (get()) {
8181 case '0':
8182 case '1':
8183 case '2':
8184 case '3':
8185 case '4':
8186 case '5':
8187 case '6':
8188 case '7':
8189 case '8':
8190 case '9': {
8191 add(current);
8192 goto scan_number_any2;
8193 }
8194
8195 default: {
8196 error_message = "invalid number; expected digit after exponent sign";
8197 return token_type::parse_error;
8198 }
8199 }
8200
8201 scan_number_any2:
8202 // we just parsed a number after the exponent or exponent sign
8203 switch (get()) {
8204 case '0':
8205 case '1':
8206 case '2':
8207 case '3':
8208 case '4':
8209 case '5':
8210 case '6':
8211 case '7':
8212 case '8':
8213 case '9': {
8214 add(current);
8215 goto scan_number_any2;
8216 }
8217
8218 default:
8219 goto scan_number_done;
8220 }
8221
8222 scan_number_done:
8223 // unget the character after the number (we only read it to know that
8224 // we are done scanning a number)
8225 unget();
8226
8227 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8228 errno = 0;
8229
8230 // try to parse integers first and fall back to floats
8231 if (number_type == token_type::value_unsigned) {
8232 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8233
8234 // we checked the number format before
8235 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8236
8237 if (errno == 0) {
8238 value_unsigned = static_cast<number_unsigned_t>(x);
8239 if (value_unsigned == x) {
8240 return token_type::value_unsigned;
8241 }
8242 }
8243 } else if (number_type == token_type::value_integer) {
8244 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8245
8246 // we checked the number format before
8247 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8248
8249 if (errno == 0) {
8250 value_integer = static_cast<number_integer_t>(x);
8251 if (value_integer == x) {
8252 return token_type::value_integer;
8253 }
8254 }
8255 }
8256
8257 // this code is reached if we parse a floating-point number or if an
8258 // integer conversion above failed
8259 strtof(value_float, token_buffer.data(), &endptr);
8260
8261 // we checked the number format before
8262 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8263
8264 return token_type::value_float;
8265 }
8266
8272 JSON_HEDLEY_NON_NULL(2)
8273 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8274 token_type return_type) {
8275 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8276 for (std::size_t i = 1; i < length; ++i) {
8277 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) !=
8278 literal_text[i])) {
8279 error_message = "invalid literal";
8280 return token_type::parse_error;
8281 }
8282 }
8283 return return_type;
8284 }
8285
8287 // input management
8289
8291 void reset() noexcept {
8292 token_buffer.clear();
8293 token_string.clear();
8294 token_string.push_back(char_traits<char_type>::to_char_type(current));
8295 }
8296
8297 /*
8298 @brief get next character from the input
8299
8300 This function provides the interface to the used input adapter. It does
8301 not throw in case the input reached EOF, but returns a
8302 `char_traits<char>::eof()` in that case. Stores the scanned characters
8303 for use in error messages.
8304
8305 @return character read from the input
8306 */
8307 char_int_type get() {
8308 ++position.chars_read_total;
8309 ++position.chars_read_current_line;
8310
8311 if (next_unget) {
8312 // just reset the next_unget variable and work with current
8313 next_unget = false;
8314 } else {
8315 current = ia.get_character();
8316 }
8317
8318 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) {
8319 token_string.push_back(char_traits<char_type>::to_char_type(current));
8320 }
8321
8322 if (current == '\n') {
8323 ++position.lines_read;
8324 position.chars_read_current_line = 0;
8325 }
8326
8327 return current;
8328 }
8329
8338 void unget() {
8339 next_unget = true;
8340
8341 --position.chars_read_total;
8342
8343 // in case we "unget" a newline, we have to also decrement the lines_read
8344 if (position.chars_read_current_line == 0) {
8345 if (position.lines_read > 0) {
8346 --position.lines_read;
8347 }
8348 } else {
8349 --position.chars_read_current_line;
8350 }
8351
8352 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) {
8353 JSON_ASSERT(!token_string.empty());
8354 token_string.pop_back();
8355 }
8356 }
8357
8359 void add(char_int_type c) {
8360 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8361 }
8362
8363 public:
8365 // value getters
8367
8369 constexpr number_integer_t get_number_integer() const noexcept { return value_integer; }
8370
8372 constexpr number_unsigned_t get_number_unsigned() const noexcept { return value_unsigned; }
8373
8375 constexpr number_float_t get_number_float() const noexcept { return value_float; }
8376
8379 string_t& get_string() { return token_buffer; }
8380
8382 // diagnostics
8384
8386 constexpr position_t get_position() const noexcept { return position; }
8387
8391 std::string get_token_string() const {
8392 // escape control characters
8393 std::string result;
8394 for (const auto c : token_string) {
8395 if (static_cast<unsigned char>(c) <= '\x1F') {
8396 // escape control characters
8397 std::array<char, 9> cs{{}};
8398 static_cast<void>((std::snprintf)(
8399 cs.data(), cs.size(), "<U+%.4X>",
8400 static_cast<unsigned char>(
8401 c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8402 result += cs.data();
8403 } else {
8404 // add character as is
8405 result.push_back(static_cast<std::string::value_type>(c));
8406 }
8407 }
8408
8409 return result;
8410 }
8411
8413 JSON_HEDLEY_RETURNS_NON_NULL
8414 constexpr const char* get_error_message() const noexcept { return error_message; }
8415
8417 // actual scanner
8419
8424 bool skip_bom() {
8425 if (get() == 0xEF) {
8426 // check if we completely parse the BOM
8427 return get() == 0xBB && get() == 0xBF;
8428 }
8429
8430 // the first character is not the beginning of the BOM; unget it to
8431 // process is later
8432 unget();
8433 return true;
8434 }
8435
8436 void skip_whitespace() {
8437 do {
8438 get();
8439 } while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8440 }
8441
8442 token_type scan() {
8443 // initially, skip the BOM
8444 if (position.chars_read_total == 0 && !skip_bom()) {
8445 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8446 return token_type::parse_error;
8447 }
8448
8449 // read next character and ignore whitespace
8450 skip_whitespace();
8451
8452 // ignore comments
8453 while (ignore_comments && current == '/') {
8454 if (!scan_comment()) {
8455 return token_type::parse_error;
8456 }
8457
8458 // skip following whitespace
8459 skip_whitespace();
8460 }
8461
8462 switch (current) {
8463 // structural characters
8464 case '[':
8465 return token_type::begin_array;
8466 case ']':
8467 return token_type::end_array;
8468 case '{':
8469 return token_type::begin_object;
8470 case '}':
8471 return token_type::end_object;
8472 case ':':
8473 return token_type::name_separator;
8474 case ',':
8475 return token_type::value_separator;
8476
8477 // literals
8478 case 't': {
8479 std::array<char_type, 4> true_literal = {
8480 {static_cast<char_type>('t'), static_cast<char_type>('r'),
8481 static_cast<char_type>('u'), static_cast<char_type>('e')}};
8482 return scan_literal(true_literal.data(), true_literal.size(),
8483 token_type::literal_true);
8484 }
8485 case 'f': {
8486 std::array<char_type, 5> false_literal = {
8487 {static_cast<char_type>('f'), static_cast<char_type>('a'),
8488 static_cast<char_type>('l'), static_cast<char_type>('s'),
8489 static_cast<char_type>('e')}};
8490 return scan_literal(false_literal.data(), false_literal.size(),
8491 token_type::literal_false);
8492 }
8493 case 'n': {
8494 std::array<char_type, 4> null_literal = {
8495 {static_cast<char_type>('n'), static_cast<char_type>('u'),
8496 static_cast<char_type>('l'), static_cast<char_type>('l')}};
8497 return scan_literal(null_literal.data(), null_literal.size(),
8498 token_type::literal_null);
8499 }
8500
8501 // string
8502 case '\"':
8503 return scan_string();
8504
8505 // number
8506 case '-':
8507 case '0':
8508 case '1':
8509 case '2':
8510 case '3':
8511 case '4':
8512 case '5':
8513 case '6':
8514 case '7':
8515 case '8':
8516 case '9':
8517 return scan_number();
8518
8519 // end of input (the null byte is needed when parsing from
8520 // string literals)
8521 case '\0':
8522 case char_traits<char_type>::eof():
8523 return token_type::end_of_input;
8524
8525 // error
8526 default:
8527 error_message = "invalid literal";
8528 return token_type::parse_error;
8529 }
8530 }
8531
8532 private:
8534 InputAdapterType ia;
8535
8537 const bool ignore_comments = false;
8538
8540 char_int_type current = char_traits<char_type>::eof();
8541
8543 bool next_unget = false;
8544
8546 position_t position{};
8547
8549 std::vector<char_type> token_string{};
8550
8552 string_t token_buffer{};
8553
8555 const char* error_message = "";
8556
8557 // number values
8558 number_integer_t value_integer = 0;
8559 number_unsigned_t value_unsigned = 0;
8560 number_float_t value_float = 0;
8561
8563 const char_int_type decimal_point_char = '.';
8564};
8565
8566} // namespace detail
8567NLOHMANN_JSON_NAMESPACE_END
8568
8569// #include <nlohmann/detail/macro_scope.hpp>
8570
8571// #include <nlohmann/detail/meta/is_sax.hpp>
8572// __ _____ _____ _____
8573// __| | __| | | | JSON for Modern C++
8574// | | |__ | | | | | | version 3.11.3
8575// |_____|_____|_____|_|___| https://github.com/nlohmann/json
8576//
8577// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
8578// SPDX-License-Identifier: MIT
8579
8580#include <cstdint> // size_t
8581#include <string> // string
8582#include <utility> // declval
8583
8584// #include <nlohmann/detail/abi_macros.hpp>
8585
8586// #include <nlohmann/detail/meta/detected.hpp>
8587
8588// #include <nlohmann/detail/meta/type_traits.hpp>
8589
8590NLOHMANN_JSON_NAMESPACE_BEGIN
8591namespace detail {
8592
8593template <typename T> using null_function_t = decltype(std::declval<T&>().null());
8594
8595template <typename T>
8596using boolean_function_t = decltype(std::declval<T&>().boolean(std::declval<bool>()));
8597
8598template <typename T, typename Integer>
8599using number_integer_function_t =
8600 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8601
8602template <typename T, typename Unsigned>
8603using number_unsigned_function_t =
8604 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8605
8606template <typename T, typename Float, typename String>
8607using number_float_function_t =
8608 decltype(std::declval<T&>().number_float(std::declval<Float>(), std::declval<const String&>()));
8609
8610template <typename T, typename String>
8611using string_function_t = decltype(std::declval<T&>().string(std::declval<String&>()));
8612
8613template <typename T, typename Binary>
8614using binary_function_t = decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8615
8616template <typename T>
8617using start_object_function_t =
8618 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8619
8620template <typename T, typename String>
8621using key_function_t = decltype(std::declval<T&>().key(std::declval<String&>()));
8622
8623template <typename T> using end_object_function_t = decltype(std::declval<T&>().end_object());
8624
8625template <typename T>
8626using start_array_function_t =
8627 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
8628
8629template <typename T> using end_array_function_t = decltype(std::declval<T&>().end_array());
8630
8631template <typename T, typename Exception>
8632using parse_error_function_t =
8633 decltype(std::declval<T&>().parse_error(std::declval<std::size_t>(),
8634 std::declval<const std::string&>(),
8635 std::declval<const Exception&>()));
8636
8637template <typename SAX, typename BasicJsonType> struct is_sax {
8638 private:
8640 "BasicJsonType must be of type basic_json<...>");
8641
8642 using number_integer_t = typename BasicJsonType::number_integer_t;
8643 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8644 using number_float_t = typename BasicJsonType::number_float_t;
8645 using string_t = typename BasicJsonType::string_t;
8646 using binary_t = typename BasicJsonType::binary_t;
8647 using exception_t = typename BasicJsonType::exception;
8648
8649 public:
8650 static constexpr bool value =
8651 is_detected_exact<bool, null_function_t, SAX>::value &&
8652 is_detected_exact<bool, boolean_function_t, SAX>::value &&
8653 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
8654 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
8655 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
8656 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
8657 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
8658 is_detected_exact<bool, start_object_function_t, SAX>::value &&
8659 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
8660 is_detected_exact<bool, end_object_function_t, SAX>::value &&
8661 is_detected_exact<bool, start_array_function_t, SAX>::value &&
8662 is_detected_exact<bool, end_array_function_t, SAX>::value &&
8663 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
8664};
8665
8666template <typename SAX, typename BasicJsonType> struct is_sax_static_asserts {
8667 private:
8669 "BasicJsonType must be of type basic_json<...>");
8670
8671 using number_integer_t = typename BasicJsonType::number_integer_t;
8672 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8673 using number_float_t = typename BasicJsonType::number_float_t;
8674 using string_t = typename BasicJsonType::string_t;
8675 using binary_t = typename BasicJsonType::binary_t;
8676 using exception_t = typename BasicJsonType::exception;
8677
8678 public:
8679 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
8680 "Missing/invalid function: bool null()");
8681 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8682 "Missing/invalid function: bool boolean(bool)");
8683 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
8684 "Missing/invalid function: bool boolean(bool)");
8685 static_assert(is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value,
8686 "Missing/invalid function: bool number_integer(number_integer_t)");
8687 static_assert(
8688 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value,
8689 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
8690 static_assert(
8691 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value,
8692 "Missing/invalid function: bool number_float(number_float_t, "
8693 "const string_t&)");
8694 static_assert(is_detected_exact<bool, string_function_t, SAX, string_t>::value,
8695 "Missing/invalid function: bool string(string_t&)");
8696 static_assert(is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
8697 "Missing/invalid function: bool binary(binary_t&)");
8698 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
8699 "Missing/invalid function: bool start_object(std::size_t)");
8700 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
8701 "Missing/invalid function: bool key(string_t&)");
8702 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
8703 "Missing/invalid function: bool end_object()");
8704 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
8705 "Missing/invalid function: bool start_array(std::size_t)");
8706 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
8707 "Missing/invalid function: bool end_array()");
8708 static_assert(is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
8709 "Missing/invalid function: bool parse_error(std::size_t, const "
8710 "std::string&, const exception&)");
8711};
8712
8713} // namespace detail
8714NLOHMANN_JSON_NAMESPACE_END
8715
8716// #include <nlohmann/detail/meta/type_traits.hpp>
8717
8718// #include <nlohmann/detail/string_concat.hpp>
8719
8720// #include <nlohmann/detail/value_t.hpp>
8721
8722NLOHMANN_JSON_NAMESPACE_BEGIN
8723namespace detail {
8724
8731
8739static inline bool little_endianness(int num = 1) noexcept {
8740 return *reinterpret_cast<char*>(&num) == 1;
8741}
8742
8744// binary reader //
8746
8750template <typename BasicJsonType, typename InputAdapterType,
8751 typename SAX = json_sax_dom_parser<BasicJsonType>>
8753 using number_integer_t = typename BasicJsonType::number_integer_t;
8754 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8755 using number_float_t = typename BasicJsonType::number_float_t;
8756 using string_t = typename BasicJsonType::string_t;
8757 using binary_t = typename BasicJsonType::binary_t;
8758 using json_sax_t = SAX;
8759 using char_type = typename InputAdapterType::char_type;
8760 using char_int_type = typename char_traits<char_type>::int_type;
8761
8762 public:
8768 explicit binary_reader(InputAdapterType&& adapter,
8769 const input_format_t format = input_format_t::json) noexcept
8770 : ia(std::move(adapter)), input_format(format) {
8772 }
8773
8774 // make class move-only
8775 binary_reader(const binary_reader&) = delete;
8777 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8778 binary_reader& operator=(const binary_reader&) = delete;
8779 binary_reader& operator=(binary_reader&&) =
8780 default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8781 ~binary_reader() = default;
8782
8791 JSON_HEDLEY_NON_NULL(3)
8792 bool sax_parse(const input_format_t format, json_sax_t* sax_, const bool strict = true,
8793 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
8794 sax = sax_;
8795 bool result = false;
8796
8797 switch (format) {
8798 case input_format_t::bson:
8799 result = parse_bson_internal();
8800 break;
8801
8802 case input_format_t::cbor:
8803 result = parse_cbor_internal(true, tag_handler);
8804 break;
8805
8806 case input_format_t::msgpack:
8807 result = parse_msgpack_internal();
8808 break;
8809
8810 case input_format_t::ubjson:
8811 case input_format_t::bjdata:
8812 result = parse_ubjson_internal();
8813 break;
8814
8815 case input_format_t::json: // LCOV_EXCL_LINE
8816 default: // LCOV_EXCL_LINE
8817 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
8818 // LCOV_EXCL_LINE
8819 }
8820
8821 // strict mode: next byte must be EOF
8822 if (result && strict) {
8823 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) {
8824 get_ignore_noop();
8825 } else {
8826 get();
8827 }
8828
8829 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof())) {
8830 return sax->parse_error(
8831 chars_read, get_token_string(),
8833 110, chars_read,
8834 exception_message(
8835 input_format,
8836 concat("expected end of input; last byte: 0x", get_token_string()),
8837 "value"),
8838 nullptr));
8839 }
8840 }
8841
8842 return result;
8843 }
8844
8845 private:
8847 // BSON //
8849
8854 bool parse_bson_internal() {
8855 std::int32_t document_size{};
8856 get_number<std::int32_t, true>(input_format_t::bson, document_size);
8857
8858 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) {
8859 return false;
8860 }
8861
8862 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ false))) {
8863 return false;
8864 }
8865
8866 return sax->end_object();
8867 }
8868
8876 bool get_bson_cstr(string_t& result) {
8877 auto out = std::back_inserter(result);
8878 while (true) {
8879 get();
8880 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) {
8881 return false;
8882 }
8883 if (current == 0x00) {
8884 return true;
8885 }
8886 *out++ = static_cast<typename string_t::value_type>(current);
8887 }
8888 }
8889
8901 template <typename NumberType> bool get_bson_string(const NumberType len, string_t& result) {
8902 if (JSON_HEDLEY_UNLIKELY(len < 1)) {
8903 auto last_token = get_token_string();
8904 return sax->parse_error(
8905 chars_read, last_token,
8906 parse_error::create(
8907 112, chars_read,
8908 exception_message(
8909 input_format_t::bson,
8910 concat("string length must be at least 1, is ", std::to_string(len)),
8911 "string"),
8912 nullptr));
8913 }
8914
8915 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) &&
8916 get() != char_traits<char_type>::eof();
8917 }
8918
8928 template <typename NumberType> bool get_bson_binary(const NumberType len, binary_t& result) {
8929 if (JSON_HEDLEY_UNLIKELY(len < 0)) {
8930 auto last_token = get_token_string();
8931 return sax->parse_error(
8932 chars_read, last_token,
8933 parse_error::create(
8934 112, chars_read,
8935 exception_message(
8936 input_format_t::bson,
8937 concat("byte array length cannot be negative, is ", std::to_string(len)),
8938 "binary"),
8939 nullptr));
8940 }
8941
8942 // All BSON binary values have a subtype
8943 std::uint8_t subtype{};
8944 get_number<std::uint8_t>(input_format_t::bson, subtype);
8945 result.set_subtype(subtype);
8946
8947 return get_binary(input_format_t::bson, len, result);
8948 }
8949
8961 bool parse_bson_element_internal(const char_int_type element_type,
8962 const std::size_t element_type_parse_position) {
8963 switch (element_type) {
8964 case 0x01: // double
8965 {
8966 double number{};
8967 return get_number<double, true>(input_format_t::bson, number) &&
8968 sax->number_float(static_cast<number_float_t>(number), "");
8969 }
8970
8971 case 0x02: // string
8972 {
8973 std::int32_t len{};
8974 string_t value;
8975 return get_number<std::int32_t, true>(input_format_t::bson, len) &&
8976 get_bson_string(len, value) && sax->string(value);
8977 }
8978
8979 case 0x03: // object
8980 {
8981 return parse_bson_internal();
8982 }
8983
8984 case 0x04: // array
8985 {
8986 return parse_bson_array();
8987 }
8988
8989 case 0x05: // binary
8990 {
8991 std::int32_t len{};
8992 binary_t value;
8993 return get_number<std::int32_t, true>(input_format_t::bson, len) &&
8994 get_bson_binary(len, value) && sax->binary(value);
8995 }
8996
8997 case 0x08: // boolean
8998 {
8999 return sax->boolean(get() != 0);
9000 }
9001
9002 case 0x0A: // null
9003 {
9004 return sax->null();
9005 }
9006
9007 case 0x10: // int32
9008 {
9009 std::int32_t value{};
9010 return get_number<std::int32_t, true>(input_format_t::bson, value) &&
9011 sax->number_integer(value);
9012 }
9013
9014 case 0x12: // int64
9015 {
9016 std::int64_t value{};
9017 return get_number<std::int64_t, true>(input_format_t::bson, value) &&
9018 sax->number_integer(value);
9019 }
9020
9021 default: // anything else not supported (yet)
9022 {
9023 std::array<char, 3> cr{{}};
9024 static_cast<void>((std::snprintf)(
9025 cr.data(), cr.size(), "%.2hhX",
9026 static_cast<unsigned char>(
9027 element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9028 const std::string cr_str{cr.data()};
9029 return sax->parse_error(
9030 element_type_parse_position, cr_str,
9031 parse_error::create(114, element_type_parse_position,
9032 concat("Unsupported BSON record type 0x", cr_str),
9033 nullptr));
9034 }
9035 }
9036 }
9037
9050 bool parse_bson_element_list(const bool is_array) {
9051 string_t key;
9052
9053 while (auto element_type = get()) {
9054 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) {
9055 return false;
9056 }
9057
9058 const std::size_t element_type_parse_position = chars_read;
9059 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) {
9060 return false;
9061 }
9062
9063 if (!is_array && !sax->key(key)) {
9064 return false;
9065 }
9066
9067 if (JSON_HEDLEY_UNLIKELY(
9068 !parse_bson_element_internal(element_type, element_type_parse_position))) {
9069 return false;
9070 }
9071
9072 // get_bson_cstr only appends
9073 key.clear();
9074 }
9075
9076 return true;
9077 }
9078
9083 bool parse_bson_array() {
9084 std::int32_t document_size{};
9085 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9086
9087 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
9088 return false;
9089 }
9090
9091 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/ true))) {
9092 return false;
9093 }
9094
9095 return sax->end_array();
9096 }
9097
9099 // CBOR //
9101
9110 bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler) {
9111 switch (get_char ? get() : current) {
9112 // EOF
9113 case char_traits<char_type>::eof():
9114 return unexpect_eof(input_format_t::cbor, "value");
9115
9116 // Integer 0x00..0x17 (0..23)
9117 case 0x00:
9118 case 0x01:
9119 case 0x02:
9120 case 0x03:
9121 case 0x04:
9122 case 0x05:
9123 case 0x06:
9124 case 0x07:
9125 case 0x08:
9126 case 0x09:
9127 case 0x0A:
9128 case 0x0B:
9129 case 0x0C:
9130 case 0x0D:
9131 case 0x0E:
9132 case 0x0F:
9133 case 0x10:
9134 case 0x11:
9135 case 0x12:
9136 case 0x13:
9137 case 0x14:
9138 case 0x15:
9139 case 0x16:
9140 case 0x17:
9141 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9142
9143 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9144 {
9145 std::uint8_t number{};
9146 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9147 }
9148
9149 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9150 {
9151 std::uint16_t number{};
9152 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9153 }
9154
9155 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9156 {
9157 std::uint32_t number{};
9158 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9159 }
9160
9161 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9162 {
9163 std::uint64_t number{};
9164 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9165 }
9166
9167 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9168 case 0x20:
9169 case 0x21:
9170 case 0x22:
9171 case 0x23:
9172 case 0x24:
9173 case 0x25:
9174 case 0x26:
9175 case 0x27:
9176 case 0x28:
9177 case 0x29:
9178 case 0x2A:
9179 case 0x2B:
9180 case 0x2C:
9181 case 0x2D:
9182 case 0x2E:
9183 case 0x2F:
9184 case 0x30:
9185 case 0x31:
9186 case 0x32:
9187 case 0x33:
9188 case 0x34:
9189 case 0x35:
9190 case 0x36:
9191 case 0x37:
9192 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9193
9194 case 0x38: // Negative integer (one-byte uint8_t follows)
9195 {
9196 std::uint8_t number{};
9197 return get_number(input_format_t::cbor, number) &&
9198 sax->number_integer(static_cast<number_integer_t>(-1) - number);
9199 }
9200
9201 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9202 {
9203 std::uint16_t number{};
9204 return get_number(input_format_t::cbor, number) &&
9205 sax->number_integer(static_cast<number_integer_t>(-1) - number);
9206 }
9207
9208 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9209 {
9210 std::uint32_t number{};
9211 return get_number(input_format_t::cbor, number) &&
9212 sax->number_integer(static_cast<number_integer_t>(-1) - number);
9213 }
9214
9215 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9216 {
9217 std::uint64_t number{};
9218 return get_number(input_format_t::cbor, number) &&
9219 sax->number_integer(static_cast<number_integer_t>(-1) -
9220 static_cast<number_integer_t>(number));
9221 }
9222
9223 // Binary data (0x00..0x17 bytes follow)
9224 case 0x40:
9225 case 0x41:
9226 case 0x42:
9227 case 0x43:
9228 case 0x44:
9229 case 0x45:
9230 case 0x46:
9231 case 0x47:
9232 case 0x48:
9233 case 0x49:
9234 case 0x4A:
9235 case 0x4B:
9236 case 0x4C:
9237 case 0x4D:
9238 case 0x4E:
9239 case 0x4F:
9240 case 0x50:
9241 case 0x51:
9242 case 0x52:
9243 case 0x53:
9244 case 0x54:
9245 case 0x55:
9246 case 0x56:
9247 case 0x57:
9248 case 0x58: // Binary data (one-byte uint8_t for n follows)
9249 case 0x59: // Binary data (two-byte uint16_t for n follow)
9250 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9251 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9252 case 0x5F: // Binary data (indefinite length)
9253 {
9254 binary_t b;
9255 return get_cbor_binary(b) && sax->binary(b);
9256 }
9257
9258 // UTF-8 string (0x00..0x17 bytes follow)
9259 case 0x60:
9260 case 0x61:
9261 case 0x62:
9262 case 0x63:
9263 case 0x64:
9264 case 0x65:
9265 case 0x66:
9266 case 0x67:
9267 case 0x68:
9268 case 0x69:
9269 case 0x6A:
9270 case 0x6B:
9271 case 0x6C:
9272 case 0x6D:
9273 case 0x6E:
9274 case 0x6F:
9275 case 0x70:
9276 case 0x71:
9277 case 0x72:
9278 case 0x73:
9279 case 0x74:
9280 case 0x75:
9281 case 0x76:
9282 case 0x77:
9283 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9284 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9285 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9286 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9287 case 0x7F: // UTF-8 string (indefinite length)
9288 {
9289 string_t s;
9290 return get_cbor_string(s) && sax->string(s);
9291 }
9292
9293 // array (0x00..0x17 data items follow)
9294 case 0x80:
9295 case 0x81:
9296 case 0x82:
9297 case 0x83:
9298 case 0x84:
9299 case 0x85:
9300 case 0x86:
9301 case 0x87:
9302 case 0x88:
9303 case 0x89:
9304 case 0x8A:
9305 case 0x8B:
9306 case 0x8C:
9307 case 0x8D:
9308 case 0x8E:
9309 case 0x8F:
9310 case 0x90:
9311 case 0x91:
9312 case 0x92:
9313 case 0x93:
9314 case 0x94:
9315 case 0x95:
9316 case 0x96:
9317 case 0x97:
9318 return get_cbor_array(conditional_static_cast<std::size_t>(
9319 static_cast<unsigned int>(current) & 0x1Fu),
9320 tag_handler);
9321
9322 case 0x98: // array (one-byte uint8_t for n follows)
9323 {
9324 std::uint8_t len{};
9325 return get_number(input_format_t::cbor, len) &&
9326 get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9327 }
9328
9329 case 0x99: // array (two-byte uint16_t for n follow)
9330 {
9331 std::uint16_t len{};
9332 return get_number(input_format_t::cbor, len) &&
9333 get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9334 }
9335
9336 case 0x9A: // array (four-byte uint32_t for n follow)
9337 {
9338 std::uint32_t len{};
9339 return get_number(input_format_t::cbor, len) &&
9340 get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9341 }
9342
9343 case 0x9B: // array (eight-byte uint64_t for n follow)
9344 {
9345 std::uint64_t len{};
9346 return get_number(input_format_t::cbor, len) &&
9347 get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9348 }
9349
9350 case 0x9F: // array (indefinite length)
9351 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9352
9353 // map (0x00..0x17 pairs of data items follow)
9354 case 0xA0:
9355 case 0xA1:
9356 case 0xA2:
9357 case 0xA3:
9358 case 0xA4:
9359 case 0xA5:
9360 case 0xA6:
9361 case 0xA7:
9362 case 0xA8:
9363 case 0xA9:
9364 case 0xAA:
9365 case 0xAB:
9366 case 0xAC:
9367 case 0xAD:
9368 case 0xAE:
9369 case 0xAF:
9370 case 0xB0:
9371 case 0xB1:
9372 case 0xB2:
9373 case 0xB3:
9374 case 0xB4:
9375 case 0xB5:
9376 case 0xB6:
9377 case 0xB7:
9378 return get_cbor_object(conditional_static_cast<std::size_t>(
9379 static_cast<unsigned int>(current) & 0x1Fu),
9380 tag_handler);
9381
9382 case 0xB8: // map (one-byte uint8_t for n follows)
9383 {
9384 std::uint8_t len{};
9385 return get_number(input_format_t::cbor, len) &&
9386 get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9387 }
9388
9389 case 0xB9: // map (two-byte uint16_t for n follow)
9390 {
9391 std::uint16_t len{};
9392 return get_number(input_format_t::cbor, len) &&
9393 get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9394 }
9395
9396 case 0xBA: // map (four-byte uint32_t for n follow)
9397 {
9398 std::uint32_t len{};
9399 return get_number(input_format_t::cbor, len) &&
9400 get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9401 }
9402
9403 case 0xBB: // map (eight-byte uint64_t for n follow)
9404 {
9405 std::uint64_t len{};
9406 return get_number(input_format_t::cbor, len) &&
9407 get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9408 }
9409
9410 case 0xBF: // map (indefinite length)
9411 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9412
9413 case 0xC6: // tagged item
9414 case 0xC7:
9415 case 0xC8:
9416 case 0xC9:
9417 case 0xCA:
9418 case 0xCB:
9419 case 0xCC:
9420 case 0xCD:
9421 case 0xCE:
9422 case 0xCF:
9423 case 0xD0:
9424 case 0xD1:
9425 case 0xD2:
9426 case 0xD3:
9427 case 0xD4:
9428 case 0xD8: // tagged item (1 bytes follow)
9429 case 0xD9: // tagged item (2 bytes follow)
9430 case 0xDA: // tagged item (4 bytes follow)
9431 case 0xDB: // tagged item (8 bytes follow)
9432 {
9433 switch (tag_handler) {
9434 case cbor_tag_handler_t::error: {
9435 auto last_token = get_token_string();
9436 return sax->parse_error(
9437 chars_read, last_token,
9438 parse_error::create(
9439 112, chars_read,
9440 exception_message(input_format_t::cbor,
9441 concat("invalid byte: 0x", last_token), "value"),
9442 nullptr));
9443 }
9444
9445 case cbor_tag_handler_t::ignore: {
9446 // ignore binary subtype
9447 switch (current) {
9448 case 0xD8: {
9449 std::uint8_t subtype_to_ignore{};
9450 get_number(input_format_t::cbor, subtype_to_ignore);
9451 break;
9452 }
9453 case 0xD9: {
9454 std::uint16_t subtype_to_ignore{};
9455 get_number(input_format_t::cbor, subtype_to_ignore);
9456 break;
9457 }
9458 case 0xDA: {
9459 std::uint32_t subtype_to_ignore{};
9460 get_number(input_format_t::cbor, subtype_to_ignore);
9461 break;
9462 }
9463 case 0xDB: {
9464 std::uint64_t subtype_to_ignore{};
9465 get_number(input_format_t::cbor, subtype_to_ignore);
9466 break;
9467 }
9468 default:
9469 break;
9470 }
9471 return parse_cbor_internal(true, tag_handler);
9472 }
9473
9474 case cbor_tag_handler_t::store: {
9475 binary_t b;
9476 // use binary subtype and store in binary container
9477 switch (current) {
9478 case 0xD8: {
9479 std::uint8_t subtype{};
9480 get_number(input_format_t::cbor, subtype);
9481 b.set_subtype(detail::conditional_static_cast<
9482 typename binary_t::subtype_type>(subtype));
9483 break;
9484 }
9485 case 0xD9: {
9486 std::uint16_t subtype{};
9487 get_number(input_format_t::cbor, subtype);
9488 b.set_subtype(detail::conditional_static_cast<
9489 typename binary_t::subtype_type>(subtype));
9490 break;
9491 }
9492 case 0xDA: {
9493 std::uint32_t subtype{};
9494 get_number(input_format_t::cbor, subtype);
9495 b.set_subtype(detail::conditional_static_cast<
9496 typename binary_t::subtype_type>(subtype));
9497 break;
9498 }
9499 case 0xDB: {
9500 std::uint64_t subtype{};
9501 get_number(input_format_t::cbor, subtype);
9502 b.set_subtype(detail::conditional_static_cast<
9503 typename binary_t::subtype_type>(subtype));
9504 break;
9505 }
9506 default:
9507 return parse_cbor_internal(true, tag_handler);
9508 }
9509 get();
9510 return get_cbor_binary(b) && sax->binary(b);
9511 }
9512
9513 default: // LCOV_EXCL_LINE
9514 JSON_ASSERT(
9515 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
9516 // LCOV_EXCL_LINE
9517 return false; // LCOV_EXCL_LINE
9518 }
9519 }
9520
9521 case 0xF4: // false
9522 return sax->boolean(false);
9523
9524 case 0xF5: // true
9525 return sax->boolean(true);
9526
9527 case 0xF6: // null
9528 return sax->null();
9529
9530 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9531 {
9532 const auto byte1_raw = get();
9533 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) {
9534 return false;
9535 }
9536 const auto byte2_raw = get();
9537 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) {
9538 return false;
9539 }
9540
9541 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9542 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9543
9544 // code from RFC 7049, Appendix D, Figure 3:
9545 // As half-precision floating-point numbers were only added
9546 // to IEEE 754 in 2008, today's programming platforms often
9547 // still only have limited support for them. It is very
9548 // easy to include at least decoding support for them even
9549 // without such support. An example of a small decoder for
9550 // half-precision floating-point numbers in the C language
9551 // is shown in Fig. 3.
9552 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9553 const double val = [&half] {
9554 const int exp = (half >> 10u) & 0x1Fu;
9555 const unsigned int mant = half & 0x3FFu;
9556 JSON_ASSERT(0 <= exp && exp <= 32);
9557 JSON_ASSERT(mant <= 1024);
9558 switch (exp) {
9559 case 0:
9560 return std::ldexp(mant, -24);
9561 case 31:
9562 return (mant == 0) ? std::numeric_limits<double>::infinity()
9563 : std::numeric_limits<double>::quiet_NaN();
9564 default:
9565 return std::ldexp(mant + 1024, exp - 25);
9566 }
9567 }();
9568 return sax->number_float((half & 0x8000u) != 0 ? static_cast<number_float_t>(-val)
9569 : static_cast<number_float_t>(val),
9570 "");
9571 }
9572
9573 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9574 {
9575 float number{};
9576 return get_number(input_format_t::cbor, number) &&
9577 sax->number_float(static_cast<number_float_t>(number), "");
9578 }
9579
9580 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9581 {
9582 double number{};
9583 return get_number(input_format_t::cbor, number) &&
9584 sax->number_float(static_cast<number_float_t>(number), "");
9585 }
9586
9587 default: // anything else (0xFF is handled inside the other types)
9588 {
9589 auto last_token = get_token_string();
9590 return sax->parse_error(
9591 chars_read, last_token,
9592 parse_error::create(112, chars_read,
9593 exception_message(input_format_t::cbor,
9594 concat("invalid byte: 0x", last_token),
9595 "value"),
9596 nullptr));
9597 }
9598 }
9599 }
9600
9612 bool get_cbor_string(string_t& result) {
9613 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) {
9614 return false;
9615 }
9616
9617 switch (current) {
9618 // UTF-8 string (0x00..0x17 bytes follow)
9619 case 0x60:
9620 case 0x61:
9621 case 0x62:
9622 case 0x63:
9623 case 0x64:
9624 case 0x65:
9625 case 0x66:
9626 case 0x67:
9627 case 0x68:
9628 case 0x69:
9629 case 0x6A:
9630 case 0x6B:
9631 case 0x6C:
9632 case 0x6D:
9633 case 0x6E:
9634 case 0x6F:
9635 case 0x70:
9636 case 0x71:
9637 case 0x72:
9638 case 0x73:
9639 case 0x74:
9640 case 0x75:
9641 case 0x76:
9642 case 0x77: {
9643 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu,
9644 result);
9645 }
9646
9647 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9648 {
9649 std::uint8_t len{};
9650 return get_number(input_format_t::cbor, len) &&
9651 get_string(input_format_t::cbor, len, result);
9652 }
9653
9654 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9655 {
9656 std::uint16_t len{};
9657 return get_number(input_format_t::cbor, len) &&
9658 get_string(input_format_t::cbor, len, result);
9659 }
9660
9661 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9662 {
9663 std::uint32_t len{};
9664 return get_number(input_format_t::cbor, len) &&
9665 get_string(input_format_t::cbor, len, result);
9666 }
9667
9668 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9669 {
9670 std::uint64_t len{};
9671 return get_number(input_format_t::cbor, len) &&
9672 get_string(input_format_t::cbor, len, result);
9673 }
9674
9675 case 0x7F: // UTF-8 string (indefinite length)
9676 {
9677 while (get() != 0xFF) {
9678 string_t chunk;
9679 if (!get_cbor_string(chunk)) {
9680 return false;
9681 }
9682 result.append(chunk);
9683 }
9684 return true;
9685 }
9686
9687 default: {
9688 auto last_token = get_token_string();
9689 return sax->parse_error(
9690 chars_read, last_token,
9691 parse_error::create(
9692 113, chars_read,
9693 exception_message(input_format_t::cbor,
9694 concat("expected length specification (0x60-0x7B) or "
9695 "indefinite string type (0x7F); last byte: 0x",
9696 last_token),
9697 "string"),
9698 nullptr));
9699 }
9700 }
9701 }
9702
9714 bool get_cbor_binary(binary_t& result) {
9715 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) {
9716 return false;
9717 }
9718
9719 switch (current) {
9720 // Binary data (0x00..0x17 bytes follow)
9721 case 0x40:
9722 case 0x41:
9723 case 0x42:
9724 case 0x43:
9725 case 0x44:
9726 case 0x45:
9727 case 0x46:
9728 case 0x47:
9729 case 0x48:
9730 case 0x49:
9731 case 0x4A:
9732 case 0x4B:
9733 case 0x4C:
9734 case 0x4D:
9735 case 0x4E:
9736 case 0x4F:
9737 case 0x50:
9738 case 0x51:
9739 case 0x52:
9740 case 0x53:
9741 case 0x54:
9742 case 0x55:
9743 case 0x56:
9744 case 0x57: {
9745 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu,
9746 result);
9747 }
9748
9749 case 0x58: // Binary data (one-byte uint8_t for n follows)
9750 {
9751 std::uint8_t len{};
9752 return get_number(input_format_t::cbor, len) &&
9753 get_binary(input_format_t::cbor, len, result);
9754 }
9755
9756 case 0x59: // Binary data (two-byte uint16_t for n follow)
9757 {
9758 std::uint16_t len{};
9759 return get_number(input_format_t::cbor, len) &&
9760 get_binary(input_format_t::cbor, len, result);
9761 }
9762
9763 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9764 {
9765 std::uint32_t len{};
9766 return get_number(input_format_t::cbor, len) &&
9767 get_binary(input_format_t::cbor, len, result);
9768 }
9769
9770 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9771 {
9772 std::uint64_t len{};
9773 return get_number(input_format_t::cbor, len) &&
9774 get_binary(input_format_t::cbor, len, result);
9775 }
9776
9777 case 0x5F: // Binary data (indefinite length)
9778 {
9779 while (get() != 0xFF) {
9780 binary_t chunk;
9781 if (!get_cbor_binary(chunk)) {
9782 return false;
9783 }
9784 result.insert(result.end(), chunk.begin(), chunk.end());
9785 }
9786 return true;
9787 }
9788
9789 default: {
9790 auto last_token = get_token_string();
9791 return sax->parse_error(
9792 chars_read, last_token,
9793 parse_error::create(
9794 113, chars_read,
9795 exception_message(
9796 input_format_t::cbor,
9797 concat("expected length specification (0x40-0x5B) or "
9798 "indefinite binary array type (0x5F); last byte: 0x",
9799 last_token),
9800 "binary"),
9801 nullptr));
9802 }
9803 }
9804 }
9805
9812 bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler) {
9813 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
9814 return false;
9815 }
9816
9817 if (len != static_cast<std::size_t>(-1)) {
9818 for (std::size_t i = 0; i < len; ++i) {
9819 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
9820 return false;
9821 }
9822 }
9823 } else {
9824 while (get() != 0xFF) {
9825 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) {
9826 return false;
9827 }
9828 }
9829 }
9830
9831 return sax->end_array();
9832 }
9833
9840 bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler) {
9841 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
9842 return false;
9843 }
9844
9845 if (len != 0) {
9846 string_t key;
9847 if (len != static_cast<std::size_t>(-1)) {
9848 for (std::size_t i = 0; i < len; ++i) {
9849 get();
9850 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
9851 return false;
9852 }
9853
9854 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
9855 return false;
9856 }
9857 key.clear();
9858 }
9859 } else {
9860 while (get() != 0xFF) {
9861 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
9862 return false;
9863 }
9864
9865 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) {
9866 return false;
9867 }
9868 key.clear();
9869 }
9870 }
9871 }
9872
9873 return sax->end_object();
9874 }
9875
9877 // MsgPack //
9879
9883 bool parse_msgpack_internal() {
9884 switch (get()) {
9885 // EOF
9886 case char_traits<char_type>::eof():
9887 return unexpect_eof(input_format_t::msgpack, "value");
9888
9889 // positive fixint
9890 case 0x00:
9891 case 0x01:
9892 case 0x02:
9893 case 0x03:
9894 case 0x04:
9895 case 0x05:
9896 case 0x06:
9897 case 0x07:
9898 case 0x08:
9899 case 0x09:
9900 case 0x0A:
9901 case 0x0B:
9902 case 0x0C:
9903 case 0x0D:
9904 case 0x0E:
9905 case 0x0F:
9906 case 0x10:
9907 case 0x11:
9908 case 0x12:
9909 case 0x13:
9910 case 0x14:
9911 case 0x15:
9912 case 0x16:
9913 case 0x17:
9914 case 0x18:
9915 case 0x19:
9916 case 0x1A:
9917 case 0x1B:
9918 case 0x1C:
9919 case 0x1D:
9920 case 0x1E:
9921 case 0x1F:
9922 case 0x20:
9923 case 0x21:
9924 case 0x22:
9925 case 0x23:
9926 case 0x24:
9927 case 0x25:
9928 case 0x26:
9929 case 0x27:
9930 case 0x28:
9931 case 0x29:
9932 case 0x2A:
9933 case 0x2B:
9934 case 0x2C:
9935 case 0x2D:
9936 case 0x2E:
9937 case 0x2F:
9938 case 0x30:
9939 case 0x31:
9940 case 0x32:
9941 case 0x33:
9942 case 0x34:
9943 case 0x35:
9944 case 0x36:
9945 case 0x37:
9946 case 0x38:
9947 case 0x39:
9948 case 0x3A:
9949 case 0x3B:
9950 case 0x3C:
9951 case 0x3D:
9952 case 0x3E:
9953 case 0x3F:
9954 case 0x40:
9955 case 0x41:
9956 case 0x42:
9957 case 0x43:
9958 case 0x44:
9959 case 0x45:
9960 case 0x46:
9961 case 0x47:
9962 case 0x48:
9963 case 0x49:
9964 case 0x4A:
9965 case 0x4B:
9966 case 0x4C:
9967 case 0x4D:
9968 case 0x4E:
9969 case 0x4F:
9970 case 0x50:
9971 case 0x51:
9972 case 0x52:
9973 case 0x53:
9974 case 0x54:
9975 case 0x55:
9976 case 0x56:
9977 case 0x57:
9978 case 0x58:
9979 case 0x59:
9980 case 0x5A:
9981 case 0x5B:
9982 case 0x5C:
9983 case 0x5D:
9984 case 0x5E:
9985 case 0x5F:
9986 case 0x60:
9987 case 0x61:
9988 case 0x62:
9989 case 0x63:
9990 case 0x64:
9991 case 0x65:
9992 case 0x66:
9993 case 0x67:
9994 case 0x68:
9995 case 0x69:
9996 case 0x6A:
9997 case 0x6B:
9998 case 0x6C:
9999 case 0x6D:
10000 case 0x6E:
10001 case 0x6F:
10002 case 0x70:
10003 case 0x71:
10004 case 0x72:
10005 case 0x73:
10006 case 0x74:
10007 case 0x75:
10008 case 0x76:
10009 case 0x77:
10010 case 0x78:
10011 case 0x79:
10012 case 0x7A:
10013 case 0x7B:
10014 case 0x7C:
10015 case 0x7D:
10016 case 0x7E:
10017 case 0x7F:
10018 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10019
10020 // fixmap
10021 case 0x80:
10022 case 0x81:
10023 case 0x82:
10024 case 0x83:
10025 case 0x84:
10026 case 0x85:
10027 case 0x86:
10028 case 0x87:
10029 case 0x88:
10030 case 0x89:
10031 case 0x8A:
10032 case 0x8B:
10033 case 0x8C:
10034 case 0x8D:
10035 case 0x8E:
10036 case 0x8F:
10037 return get_msgpack_object(conditional_static_cast<std::size_t>(
10038 static_cast<unsigned int>(current) & 0x0Fu));
10039
10040 // fixarray
10041 case 0x90:
10042 case 0x91:
10043 case 0x92:
10044 case 0x93:
10045 case 0x94:
10046 case 0x95:
10047 case 0x96:
10048 case 0x97:
10049 case 0x98:
10050 case 0x99:
10051 case 0x9A:
10052 case 0x9B:
10053 case 0x9C:
10054 case 0x9D:
10055 case 0x9E:
10056 case 0x9F:
10057 return get_msgpack_array(conditional_static_cast<std::size_t>(
10058 static_cast<unsigned int>(current) & 0x0Fu));
10059
10060 // fixstr
10061 case 0xA0:
10062 case 0xA1:
10063 case 0xA2:
10064 case 0xA3:
10065 case 0xA4:
10066 case 0xA5:
10067 case 0xA6:
10068 case 0xA7:
10069 case 0xA8:
10070 case 0xA9:
10071 case 0xAA:
10072 case 0xAB:
10073 case 0xAC:
10074 case 0xAD:
10075 case 0xAE:
10076 case 0xAF:
10077 case 0xB0:
10078 case 0xB1:
10079 case 0xB2:
10080 case 0xB3:
10081 case 0xB4:
10082 case 0xB5:
10083 case 0xB6:
10084 case 0xB7:
10085 case 0xB8:
10086 case 0xB9:
10087 case 0xBA:
10088 case 0xBB:
10089 case 0xBC:
10090 case 0xBD:
10091 case 0xBE:
10092 case 0xBF:
10093 case 0xD9: // str 8
10094 case 0xDA: // str 16
10095 case 0xDB: // str 32
10096 {
10097 string_t s;
10098 return get_msgpack_string(s) && sax->string(s);
10099 }
10100
10101 case 0xC0: // nil
10102 return sax->null();
10103
10104 case 0xC2: // false
10105 return sax->boolean(false);
10106
10107 case 0xC3: // true
10108 return sax->boolean(true);
10109
10110 case 0xC4: // bin 8
10111 case 0xC5: // bin 16
10112 case 0xC6: // bin 32
10113 case 0xC7: // ext 8
10114 case 0xC8: // ext 16
10115 case 0xC9: // ext 32
10116 case 0xD4: // fixext 1
10117 case 0xD5: // fixext 2
10118 case 0xD6: // fixext 4
10119 case 0xD7: // fixext 8
10120 case 0xD8: // fixext 16
10121 {
10122 binary_t b;
10123 return get_msgpack_binary(b) && sax->binary(b);
10124 }
10125
10126 case 0xCA: // float 32
10127 {
10128 float number{};
10129 return get_number(input_format_t::msgpack, number) &&
10130 sax->number_float(static_cast<number_float_t>(number), "");
10131 }
10132
10133 case 0xCB: // float 64
10134 {
10135 double number{};
10136 return get_number(input_format_t::msgpack, number) &&
10137 sax->number_float(static_cast<number_float_t>(number), "");
10138 }
10139
10140 case 0xCC: // uint 8
10141 {
10142 std::uint8_t number{};
10143 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10144 }
10145
10146 case 0xCD: // uint 16
10147 {
10148 std::uint16_t number{};
10149 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10150 }
10151
10152 case 0xCE: // uint 32
10153 {
10154 std::uint32_t number{};
10155 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10156 }
10157
10158 case 0xCF: // uint 64
10159 {
10160 std::uint64_t number{};
10161 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10162 }
10163
10164 case 0xD0: // int 8
10165 {
10166 std::int8_t number{};
10167 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10168 }
10169
10170 case 0xD1: // int 16
10171 {
10172 std::int16_t number{};
10173 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10174 }
10175
10176 case 0xD2: // int 32
10177 {
10178 std::int32_t number{};
10179 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10180 }
10181
10182 case 0xD3: // int 64
10183 {
10184 std::int64_t number{};
10185 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10186 }
10187
10188 case 0xDC: // array 16
10189 {
10190 std::uint16_t len{};
10191 return get_number(input_format_t::msgpack, len) &&
10192 get_msgpack_array(static_cast<std::size_t>(len));
10193 }
10194
10195 case 0xDD: // array 32
10196 {
10197 std::uint32_t len{};
10198 return get_number(input_format_t::msgpack, len) &&
10199 get_msgpack_array(conditional_static_cast<std::size_t>(len));
10200 }
10201
10202 case 0xDE: // map 16
10203 {
10204 std::uint16_t len{};
10205 return get_number(input_format_t::msgpack, len) &&
10206 get_msgpack_object(static_cast<std::size_t>(len));
10207 }
10208
10209 case 0xDF: // map 32
10210 {
10211 std::uint32_t len{};
10212 return get_number(input_format_t::msgpack, len) &&
10213 get_msgpack_object(conditional_static_cast<std::size_t>(len));
10214 }
10215
10216 // negative fixint
10217 case 0xE0:
10218 case 0xE1:
10219 case 0xE2:
10220 case 0xE3:
10221 case 0xE4:
10222 case 0xE5:
10223 case 0xE6:
10224 case 0xE7:
10225 case 0xE8:
10226 case 0xE9:
10227 case 0xEA:
10228 case 0xEB:
10229 case 0xEC:
10230 case 0xED:
10231 case 0xEE:
10232 case 0xEF:
10233 case 0xF0:
10234 case 0xF1:
10235 case 0xF2:
10236 case 0xF3:
10237 case 0xF4:
10238 case 0xF5:
10239 case 0xF6:
10240 case 0xF7:
10241 case 0xF8:
10242 case 0xF9:
10243 case 0xFA:
10244 case 0xFB:
10245 case 0xFC:
10246 case 0xFD:
10247 case 0xFE:
10248 case 0xFF:
10249 return sax->number_integer(static_cast<std::int8_t>(current));
10250
10251 default: // anything else
10252 {
10253 auto last_token = get_token_string();
10254 return sax->parse_error(
10255 chars_read, last_token,
10256 parse_error::create(112, chars_read,
10257 exception_message(input_format_t::msgpack,
10258 concat("invalid byte: 0x", last_token),
10259 "value"),
10260 nullptr));
10261 }
10262 }
10263 }
10264
10275 bool get_msgpack_string(string_t& result) {
10276 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) {
10277 return false;
10278 }
10279
10280 switch (current) {
10281 // fixstr
10282 case 0xA0:
10283 case 0xA1:
10284 case 0xA2:
10285 case 0xA3:
10286 case 0xA4:
10287 case 0xA5:
10288 case 0xA6:
10289 case 0xA7:
10290 case 0xA8:
10291 case 0xA9:
10292 case 0xAA:
10293 case 0xAB:
10294 case 0xAC:
10295 case 0xAD:
10296 case 0xAE:
10297 case 0xAF:
10298 case 0xB0:
10299 case 0xB1:
10300 case 0xB2:
10301 case 0xB3:
10302 case 0xB4:
10303 case 0xB5:
10304 case 0xB6:
10305 case 0xB7:
10306 case 0xB8:
10307 case 0xB9:
10308 case 0xBA:
10309 case 0xBB:
10310 case 0xBC:
10311 case 0xBD:
10312 case 0xBE:
10313 case 0xBF: {
10314 return get_string(input_format_t::msgpack,
10315 static_cast<unsigned int>(current) & 0x1Fu, result);
10316 }
10317
10318 case 0xD9: // str 8
10319 {
10320 std::uint8_t len{};
10321 return get_number(input_format_t::msgpack, len) &&
10322 get_string(input_format_t::msgpack, len, result);
10323 }
10324
10325 case 0xDA: // str 16
10326 {
10327 std::uint16_t len{};
10328 return get_number(input_format_t::msgpack, len) &&
10329 get_string(input_format_t::msgpack, len, result);
10330 }
10331
10332 case 0xDB: // str 32
10333 {
10334 std::uint32_t len{};
10335 return get_number(input_format_t::msgpack, len) &&
10336 get_string(input_format_t::msgpack, len, result);
10337 }
10338
10339 default: {
10340 auto last_token = get_token_string();
10341 return sax->parse_error(
10342 chars_read, last_token,
10343 parse_error::create(
10344 113, chars_read,
10345 exception_message(input_format_t::msgpack,
10346 concat("expected length specification "
10347 "(0xA0-0xBF, 0xD9-0xDB); last byte: 0x",
10348 last_token),
10349 "string"),
10350 nullptr));
10351 }
10352 }
10353 }
10354
10365 bool get_msgpack_binary(binary_t& result) {
10366 // helper function to set the subtype
10367 auto assign_and_return_true = [&result](std::int8_t subtype) {
10368 result.set_subtype(static_cast<std::uint8_t>(subtype));
10369 return true;
10370 };
10371
10372 switch (current) {
10373 case 0xC4: // bin 8
10374 {
10375 std::uint8_t len{};
10376 return get_number(input_format_t::msgpack, len) &&
10377 get_binary(input_format_t::msgpack, len, result);
10378 }
10379
10380 case 0xC5: // bin 16
10381 {
10382 std::uint16_t len{};
10383 return get_number(input_format_t::msgpack, len) &&
10384 get_binary(input_format_t::msgpack, len, result);
10385 }
10386
10387 case 0xC6: // bin 32
10388 {
10389 std::uint32_t len{};
10390 return get_number(input_format_t::msgpack, len) &&
10391 get_binary(input_format_t::msgpack, len, result);
10392 }
10393
10394 case 0xC7: // ext 8
10395 {
10396 std::uint8_t len{};
10397 std::int8_t subtype{};
10398 return get_number(input_format_t::msgpack, len) &&
10399 get_number(input_format_t::msgpack, subtype) &&
10400 get_binary(input_format_t::msgpack, len, result) &&
10401 assign_and_return_true(subtype);
10402 }
10403
10404 case 0xC8: // ext 16
10405 {
10406 std::uint16_t len{};
10407 std::int8_t subtype{};
10408 return get_number(input_format_t::msgpack, len) &&
10409 get_number(input_format_t::msgpack, subtype) &&
10410 get_binary(input_format_t::msgpack, len, result) &&
10411 assign_and_return_true(subtype);
10412 }
10413
10414 case 0xC9: // ext 32
10415 {
10416 std::uint32_t len{};
10417 std::int8_t subtype{};
10418 return get_number(input_format_t::msgpack, len) &&
10419 get_number(input_format_t::msgpack, subtype) &&
10420 get_binary(input_format_t::msgpack, len, result) &&
10421 assign_and_return_true(subtype);
10422 }
10423
10424 case 0xD4: // fixext 1
10425 {
10426 std::int8_t subtype{};
10427 return get_number(input_format_t::msgpack, subtype) &&
10428 get_binary(input_format_t::msgpack, 1, result) &&
10429 assign_and_return_true(subtype);
10430 }
10431
10432 case 0xD5: // fixext 2
10433 {
10434 std::int8_t subtype{};
10435 return get_number(input_format_t::msgpack, subtype) &&
10436 get_binary(input_format_t::msgpack, 2, result) &&
10437 assign_and_return_true(subtype);
10438 }
10439
10440 case 0xD6: // fixext 4
10441 {
10442 std::int8_t subtype{};
10443 return get_number(input_format_t::msgpack, subtype) &&
10444 get_binary(input_format_t::msgpack, 4, result) &&
10445 assign_and_return_true(subtype);
10446 }
10447
10448 case 0xD7: // fixext 8
10449 {
10450 std::int8_t subtype{};
10451 return get_number(input_format_t::msgpack, subtype) &&
10452 get_binary(input_format_t::msgpack, 8, result) &&
10453 assign_and_return_true(subtype);
10454 }
10455
10456 case 0xD8: // fixext 16
10457 {
10458 std::int8_t subtype{};
10459 return get_number(input_format_t::msgpack, subtype) &&
10460 get_binary(input_format_t::msgpack, 16, result) &&
10461 assign_and_return_true(subtype);
10462 }
10463
10464 default: // LCOV_EXCL_LINE
10465 return false; // LCOV_EXCL_LINE
10466 }
10467 }
10468
10473 bool get_msgpack_array(const std::size_t len) {
10474 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
10475 return false;
10476 }
10477
10478 for (std::size_t i = 0; i < len; ++i) {
10479 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
10480 return false;
10481 }
10482 }
10483
10484 return sax->end_array();
10485 }
10486
10491 bool get_msgpack_object(const std::size_t len) {
10492 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
10493 return false;
10494 }
10495
10496 string_t key;
10497 for (std::size_t i = 0; i < len; ++i) {
10498 get();
10499 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) {
10500 return false;
10501 }
10502
10503 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
10504 return false;
10505 }
10506 key.clear();
10507 }
10508
10509 return sax->end_object();
10510 }
10511
10513 // UBJSON //
10515
10523 bool parse_ubjson_internal(const bool get_char = true) {
10524 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10525 }
10526
10541 bool get_ubjson_string(string_t& result, const bool get_char = true) {
10542 if (get_char) {
10543 get(); // TODO(niels): may we ignore N here?
10544 }
10545
10546 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) {
10547 return false;
10548 }
10549
10550 switch (current) {
10551 case 'U': {
10552 std::uint8_t len{};
10553 return get_number(input_format, len) && get_string(input_format, len, result);
10554 }
10555
10556 case 'i': {
10557 std::int8_t len{};
10558 return get_number(input_format, len) && get_string(input_format, len, result);
10559 }
10560
10561 case 'I': {
10562 std::int16_t len{};
10563 return get_number(input_format, len) && get_string(input_format, len, result);
10564 }
10565
10566 case 'l': {
10567 std::int32_t len{};
10568 return get_number(input_format, len) && get_string(input_format, len, result);
10569 }
10570
10571 case 'L': {
10572 std::int64_t len{};
10573 return get_number(input_format, len) && get_string(input_format, len, result);
10574 }
10575
10576 case 'u': {
10577 if (input_format != input_format_t::bjdata) {
10578 break;
10579 }
10580 std::uint16_t len{};
10581 return get_number(input_format, len) && get_string(input_format, len, result);
10582 }
10583
10584 case 'm': {
10585 if (input_format != input_format_t::bjdata) {
10586 break;
10587 }
10588 std::uint32_t len{};
10589 return get_number(input_format, len) && get_string(input_format, len, result);
10590 }
10591
10592 case 'M': {
10593 if (input_format != input_format_t::bjdata) {
10594 break;
10595 }
10596 std::uint64_t len{};
10597 return get_number(input_format, len) && get_string(input_format, len, result);
10598 }
10599
10600 default:
10601 break;
10602 }
10603 auto last_token = get_token_string();
10604 std::string message;
10605
10606 if (input_format != input_format_t::bjdata) {
10607 message =
10608 "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
10609 } else {
10610 message = "expected length type specification (U, i, u, I, m, l, M, L); "
10611 "last byte: 0x" +
10612 last_token;
10613 }
10614 return sax->parse_error(
10615 chars_read, last_token,
10616 parse_error::create(113, chars_read, exception_message(input_format, message, "string"),
10617 nullptr));
10618 }
10619
10624 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) {
10625 std::pair<std::size_t, char_int_type> size_and_type;
10626 size_t dimlen = 0;
10627 bool no_ndarray = true;
10628
10629 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) {
10630 return false;
10631 }
10632
10633 if (size_and_type.first != npos) {
10634 if (size_and_type.second != 0) {
10635 if (size_and_type.second != 'N') {
10636 for (std::size_t i = 0; i < size_and_type.first; ++i) {
10637 if (JSON_HEDLEY_UNLIKELY(
10638 !get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) {
10639 return false;
10640 }
10641 dim.push_back(dimlen);
10642 }
10643 }
10644 } else {
10645 for (std::size_t i = 0; i < size_and_type.first; ++i) {
10646 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) {
10647 return false;
10648 }
10649 dim.push_back(dimlen);
10650 }
10651 }
10652 } else {
10653 while (current != ']') {
10654 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) {
10655 return false;
10656 }
10657 dim.push_back(dimlen);
10658 get_ignore_noop();
10659 }
10660 }
10661 return true;
10662 }
10663
10674 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) {
10675 if (prefix == 0) {
10676 prefix = get_ignore_noop();
10677 }
10678
10679 switch (prefix) {
10680 case 'U': {
10681 std::uint8_t number{};
10682 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10683 return false;
10684 }
10685 result = static_cast<std::size_t>(number);
10686 return true;
10687 }
10688
10689 case 'i': {
10690 std::int8_t number{};
10691 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10692 return false;
10693 }
10694 if (number < 0) {
10695 return sax->parse_error(
10696 chars_read, get_token_string(),
10697 parse_error::create(
10698 113, chars_read,
10699 exception_message(input_format,
10700 "count in an optimized container must be positive",
10701 "size"),
10702 nullptr));
10703 }
10704 result = static_cast<std::size_t>(
10705 number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c):
10706 // number is not a char
10707 return true;
10708 }
10709
10710 case 'I': {
10711 std::int16_t number{};
10712 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10713 return false;
10714 }
10715 if (number < 0) {
10716 return sax->parse_error(
10717 chars_read, get_token_string(),
10718 parse_error::create(
10719 113, chars_read,
10720 exception_message(input_format,
10721 "count in an optimized container must be positive",
10722 "size"),
10723 nullptr));
10724 }
10725 result = static_cast<std::size_t>(number);
10726 return true;
10727 }
10728
10729 case 'l': {
10730 std::int32_t number{};
10731 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10732 return false;
10733 }
10734 if (number < 0) {
10735 return sax->parse_error(
10736 chars_read, get_token_string(),
10737 parse_error::create(
10738 113, chars_read,
10739 exception_message(input_format,
10740 "count in an optimized container must be positive",
10741 "size"),
10742 nullptr));
10743 }
10744 result = static_cast<std::size_t>(number);
10745 return true;
10746 }
10747
10748 case 'L': {
10749 std::int64_t number{};
10750 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10751 return false;
10752 }
10753 if (number < 0) {
10754 return sax->parse_error(
10755 chars_read, get_token_string(),
10756 parse_error::create(
10757 113, chars_read,
10758 exception_message(input_format,
10759 "count in an optimized container must be positive",
10760 "size"),
10761 nullptr));
10762 }
10763 if (!value_in_range_of<std::size_t>(number)) {
10764 return sax->parse_error(
10765 chars_read, get_token_string(),
10766 out_of_range::create(
10767 408, exception_message(input_format, "integer value overflow", "size"),
10768 nullptr));
10769 }
10770 result = static_cast<std::size_t>(number);
10771 return true;
10772 }
10773
10774 case 'u': {
10775 if (input_format != input_format_t::bjdata) {
10776 break;
10777 }
10778 std::uint16_t number{};
10779 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10780 return false;
10781 }
10782 result = static_cast<std::size_t>(number);
10783 return true;
10784 }
10785
10786 case 'm': {
10787 if (input_format != input_format_t::bjdata) {
10788 break;
10789 }
10790 std::uint32_t number{};
10791 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10792 return false;
10793 }
10794 result = conditional_static_cast<std::size_t>(number);
10795 return true;
10796 }
10797
10798 case 'M': {
10799 if (input_format != input_format_t::bjdata) {
10800 break;
10801 }
10802 std::uint64_t number{};
10803 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
10804 return false;
10805 }
10806 if (!value_in_range_of<std::size_t>(number)) {
10807 return sax->parse_error(
10808 chars_read, get_token_string(),
10809 out_of_range::create(
10810 408, exception_message(input_format, "integer value overflow", "size"),
10811 nullptr));
10812 }
10813 result = detail::conditional_static_cast<std::size_t>(number);
10814 return true;
10815 }
10816
10817 case '[': {
10818 if (input_format != input_format_t::bjdata) {
10819 break;
10820 }
10821 if (is_ndarray) // ndarray dimensional vector can only contain integers,
10822 // and can not embed another array
10823 {
10824 return sax->parse_error(
10825 chars_read, get_token_string(),
10826 parse_error::create(
10827 113, chars_read,
10828 exception_message(input_format,
10829 "ndarray dimensional vector is not allowed", "size"),
10830 nullptr));
10831 }
10832 std::vector<size_t> dim;
10833 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) {
10834 return false;
10835 }
10836 if (dim.size() == 1 ||
10837 (dim.size() == 2 &&
10838 dim.at(0) == 1)) // return normal array size if 1D row vector
10839 {
10840 result = dim.at(dim.size() - 1);
10841 return true;
10842 }
10843 if (!dim.empty()) // if ndarray, convert to an object in JData annotated
10844 // array format
10845 {
10846 for (auto i : dim) // test if any dimension in an ndarray is 0, if so,
10847 // return a 1D empty container
10848 {
10849 if (i == 0) {
10850 result = 0;
10851 return true;
10852 }
10853 }
10854
10855 string_t key = "_ArraySize_";
10856 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) ||
10857 !sax->start_array(dim.size()))) {
10858 return false;
10859 }
10860 result = 1;
10861 for (auto i : dim) {
10862 result *= i;
10863 if (result == 0 ||
10864 result == npos) // because dim elements shall not have zeros, result = 0
10865 // means overflow happened; it also can't be npos as it
10866 // is used to initialize size in get_ubjson_size_type()
10867 {
10868 return sax->parse_error(
10869 chars_read, get_token_string(),
10870 out_of_range::create(
10871 408,
10872 exception_message(input_format,
10873 "excessive ndarray size caused overflow",
10874 "size"),
10875 nullptr));
10876 }
10877 if (JSON_HEDLEY_UNLIKELY(
10878 !sax->number_unsigned(static_cast<number_unsigned_t>(i)))) {
10879 return false;
10880 }
10881 }
10882 is_ndarray = true;
10883 return sax->end_array();
10884 }
10885 result = 0;
10886 return true;
10887 }
10888
10889 default:
10890 break;
10891 }
10892 auto last_token = get_token_string();
10893 std::string message;
10894
10895 if (input_format != input_format_t::bjdata) {
10896 message = "expected length type specification (U, i, I, l, L) after '#'; "
10897 "last byte: 0x" +
10898 last_token;
10899 } else {
10900 message = "expected length type specification (U, i, u, I, m, l, M, L) "
10901 "after '#'; last byte: 0x" +
10902 last_token;
10903 }
10904 return sax->parse_error(
10905 chars_read, last_token,
10906 parse_error::create(113, chars_read, exception_message(input_format, message, "size"),
10907 nullptr));
10908 }
10909
10922 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result,
10923 bool inside_ndarray = false) {
10924 result.first = npos; // size
10925 result.second = 0; // type
10926 bool is_ndarray = false;
10927
10928 get_ignore_noop();
10929
10930 if (current == '$') {
10931 result.second = get(); // must not ignore 'N', because 'N' maybe the type
10932 if (input_format == input_format_t::bjdata &&
10933 JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(),
10934 bjd_optimized_type_markers.end(),
10935 result.second))) {
10936 auto last_token = get_token_string();
10937 return sax->parse_error(
10938 chars_read, last_token,
10939 parse_error::create(
10940 112, chars_read,
10941 exception_message(input_format,
10942 concat("marker 0x", last_token,
10943 " is not a permitted optimized array type"),
10944 "type"),
10945 nullptr));
10946 }
10947
10948 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) {
10949 return false;
10950 }
10951
10952 get_ignore_noop();
10953 if (JSON_HEDLEY_UNLIKELY(current != '#')) {
10954 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) {
10955 return false;
10956 }
10957 auto last_token = get_token_string();
10958 return sax->parse_error(
10959 chars_read, last_token,
10960 parse_error::create(
10961 112, chars_read,
10962 exception_message(
10963 input_format,
10964 concat("expected '#' after type information; last byte: 0x",
10965 last_token),
10966 "size"),
10967 nullptr));
10968 }
10969
10970 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
10971 if (input_format == input_format_t::bjdata && is_ndarray) {
10972 if (inside_ndarray) {
10973 return sax->parse_error(
10974 chars_read, get_token_string(),
10975 parse_error::create(
10976 112, chars_read,
10977 exception_message(input_format, "ndarray can not be recursive", "size"),
10978 nullptr));
10979 }
10980 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON
10981 // and BJData markers should be ASCII letters
10982 }
10983 return is_error;
10984 }
10985
10986 if (current == '#') {
10987 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
10988 if (input_format == input_format_t::bjdata && is_ndarray) {
10989 return sax->parse_error(
10990 chars_read, get_token_string(),
10991 parse_error::create(112, chars_read,
10992 exception_message(input_format,
10993 "ndarray requires both type and size",
10994 "size"),
10995 nullptr));
10996 }
10997 return is_error;
10998 }
10999
11000 return true;
11001 }
11002
11007 bool get_ubjson_value(const char_int_type prefix) {
11008 switch (prefix) {
11009 case char_traits<char_type>::eof(): // EOF
11010 return unexpect_eof(input_format, "value");
11011
11012 case 'T': // true
11013 return sax->boolean(true);
11014 case 'F': // false
11015 return sax->boolean(false);
11016
11017 case 'Z': // null
11018 return sax->null();
11019
11020 case 'U': {
11021 std::uint8_t number{};
11022 return get_number(input_format, number) && sax->number_unsigned(number);
11023 }
11024
11025 case 'i': {
11026 std::int8_t number{};
11027 return get_number(input_format, number) && sax->number_integer(number);
11028 }
11029
11030 case 'I': {
11031 std::int16_t number{};
11032 return get_number(input_format, number) && sax->number_integer(number);
11033 }
11034
11035 case 'l': {
11036 std::int32_t number{};
11037 return get_number(input_format, number) && sax->number_integer(number);
11038 }
11039
11040 case 'L': {
11041 std::int64_t number{};
11042 return get_number(input_format, number) && sax->number_integer(number);
11043 }
11044
11045 case 'u': {
11046 if (input_format != input_format_t::bjdata) {
11047 break;
11048 }
11049 std::uint16_t number{};
11050 return get_number(input_format, number) && sax->number_unsigned(number);
11051 }
11052
11053 case 'm': {
11054 if (input_format != input_format_t::bjdata) {
11055 break;
11056 }
11057 std::uint32_t number{};
11058 return get_number(input_format, number) && sax->number_unsigned(number);
11059 }
11060
11061 case 'M': {
11062 if (input_format != input_format_t::bjdata) {
11063 break;
11064 }
11065 std::uint64_t number{};
11066 return get_number(input_format, number) && sax->number_unsigned(number);
11067 }
11068
11069 case 'h': {
11070 if (input_format != input_format_t::bjdata) {
11071 break;
11072 }
11073 const auto byte1_raw = get();
11074 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11075 return false;
11076 }
11077 const auto byte2_raw = get();
11078 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11079 return false;
11080 }
11081
11082 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11083 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11084
11085 // code from RFC 7049, Appendix D, Figure 3:
11086 // As half-precision floating-point numbers were only added
11087 // to IEEE 754 in 2008, today's programming platforms often
11088 // still only have limited support for them. It is very
11089 // easy to include at least decoding support for them even
11090 // without such support. An example of a small decoder for
11091 // half-precision floating-point numbers in the C language
11092 // is shown in Fig. 3.
11093 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11094 const double val = [&half] {
11095 const int exp = (half >> 10u) & 0x1Fu;
11096 const unsigned int mant = half & 0x3FFu;
11097 JSON_ASSERT(0 <= exp && exp <= 32);
11098 JSON_ASSERT(mant <= 1024);
11099 switch (exp) {
11100 case 0:
11101 return std::ldexp(mant, -24);
11102 case 31:
11103 return (mant == 0) ? std::numeric_limits<double>::infinity()
11104 : std::numeric_limits<double>::quiet_NaN();
11105 default:
11106 return std::ldexp(mant + 1024, exp - 25);
11107 }
11108 }();
11109 return sax->number_float((half & 0x8000u) != 0 ? static_cast<number_float_t>(-val)
11110 : static_cast<number_float_t>(val),
11111 "");
11112 }
11113
11114 case 'd': {
11115 float number{};
11116 return get_number(input_format, number) &&
11117 sax->number_float(static_cast<number_float_t>(number), "");
11118 }
11119
11120 case 'D': {
11121 double number{};
11122 return get_number(input_format, number) &&
11123 sax->number_float(static_cast<number_float_t>(number), "");
11124 }
11125
11126 case 'H': {
11127 return get_ubjson_high_precision_number();
11128 }
11129
11130 case 'C': // char
11131 {
11132 get();
11133 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) {
11134 return false;
11135 }
11136 if (JSON_HEDLEY_UNLIKELY(current > 127)) {
11137 auto last_token = get_token_string();
11138 return sax->parse_error(
11139 chars_read, last_token,
11140 parse_error::create(
11141 113, chars_read,
11142 exception_message(input_format,
11143 concat("byte after 'C' must be in range "
11144 "0x00..0x7F; last byte: 0x",
11145 last_token),
11146 "char"),
11147 nullptr));
11148 }
11149 string_t s(1, static_cast<typename string_t::value_type>(current));
11150 return sax->string(s);
11151 }
11152
11153 case 'S': // string
11154 {
11155 string_t s;
11156 return get_ubjson_string(s) && sax->string(s);
11157 }
11158
11159 case '[': // array
11160 return get_ubjson_array();
11161
11162 case '{': // object
11163 return get_ubjson_object();
11164
11165 default: // anything else
11166 break;
11167 }
11168 auto last_token = get_token_string();
11169 return sax->parse_error(
11170 chars_read, last_token,
11171 parse_error::create(
11172 112, chars_read,
11173 exception_message(input_format, "invalid byte: 0x" + last_token, "value"),
11174 nullptr));
11175 }
11176
11180 bool get_ubjson_array() {
11181 std::pair<std::size_t, char_int_type> size_and_type;
11182 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11183 return false;
11184 }
11185
11186 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an
11187 // object in JData annotated array format
11188 // (https://github.com/NeuroJSON/jdata):
11189 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" :
11190 // [v1, v2, ...]}
11191
11192 if (input_format == input_format_t::bjdata && size_and_type.first != npos &&
11193 (size_and_type.second & (1 << 8)) != 0) {
11194 size_and_type.second &=
11195 ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we
11196 // remove the bit to restore the type marker
11197 auto it =
11198 std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second,
11199 [](const bjd_type& p, char_int_type t) { return p.first < t; });
11200 string_t key = "_ArrayType_";
11201 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() ||
11202 it->first != size_and_type.second)) {
11203 auto last_token = get_token_string();
11204 return sax->parse_error(
11205 chars_read, last_token,
11206 parse_error::create(
11207 112, chars_read,
11208 exception_message(input_format, "invalid byte: 0x" + last_token, "type"),
11209 nullptr));
11210 }
11211
11212 string_t type = it->second; // sax->string() takes a reference
11213 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) {
11214 return false;
11215 }
11216
11217 if (size_and_type.second == 'C') {
11218 size_and_type.second = 'U';
11219 }
11220
11221 key = "_ArrayData_";
11222 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first))) {
11223 return false;
11224 }
11225
11226 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11227 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11228 return false;
11229 }
11230 }
11231
11232 return (sax->end_array() && sax->end_object());
11233 }
11234
11235 if (size_and_type.first != npos) {
11236 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) {
11237 return false;
11238 }
11239
11240 if (size_and_type.second != 0) {
11241 if (size_and_type.second != 'N') {
11242 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11243 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11244 return false;
11245 }
11246 }
11247 }
11248 } else {
11249 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11250 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11251 return false;
11252 }
11253 }
11254 }
11255 } else {
11256 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
11257 return false;
11258 }
11259
11260 while (current != ']') {
11261 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) {
11262 return false;
11263 }
11264 get_ignore_noop();
11265 }
11266 }
11267
11268 return sax->end_array();
11269 }
11270
11274 bool get_ubjson_object() {
11275 std::pair<std::size_t, char_int_type> size_and_type;
11276 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11277 return false;
11278 }
11279
11280 // do not accept ND-array size in objects in BJData
11281 if (input_format == input_format_t::bjdata && size_and_type.first != npos &&
11282 (size_and_type.second & (1 << 8)) != 0) {
11283 auto last_token = get_token_string();
11284 return sax->parse_error(
11285 chars_read, last_token,
11286 parse_error::create(
11287 112, chars_read,
11288 exception_message(input_format,
11289 "BJData object does not support ND-array size "
11290 "in optimized format",
11291 "object"),
11292 nullptr));
11293 }
11294
11295 string_t key;
11296 if (size_and_type.first != npos) {
11297 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) {
11298 return false;
11299 }
11300
11301 if (size_and_type.second != 0) {
11302 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11303 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11304 return false;
11305 }
11306 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11307 return false;
11308 }
11309 key.clear();
11310 }
11311 } else {
11312 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11313 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11314 return false;
11315 }
11316 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11317 return false;
11318 }
11319 key.clear();
11320 }
11321 }
11322 } else {
11323 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) {
11324 return false;
11325 }
11326
11327 while (current != '}') {
11328 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) {
11329 return false;
11330 }
11331 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11332 return false;
11333 }
11334 get_ignore_noop();
11335 key.clear();
11336 }
11337 }
11338
11339 return sax->end_object();
11340 }
11341
11342 // Note, no reader for UBJSON binary types is implemented because they do
11343 // not exist
11344
11345 bool get_ubjson_high_precision_number() {
11346 // get size of following number string
11347 std::size_t size{};
11348 bool no_ndarray = true;
11349 auto res = get_ubjson_size_value(size, no_ndarray);
11350 if (JSON_HEDLEY_UNLIKELY(!res)) {
11351 return res;
11352 }
11353
11354 // get number string
11355 std::vector<char> number_vector;
11356 for (std::size_t i = 0; i < size; ++i) {
11357 get();
11358 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) {
11359 return false;
11360 }
11361 number_vector.push_back(static_cast<char>(current));
11362 }
11363
11364 // parse number string
11365 using ia_type = decltype(detail::input_adapter(number_vector));
11366 auto number_lexer =
11367 detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11368 const auto result_number = number_lexer.scan();
11369 const auto number_string = number_lexer.get_token_string();
11370 const auto result_remainder = number_lexer.scan();
11371
11372 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11373
11374 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) {
11375 return sax->parse_error(
11376 chars_read, number_string,
11377 parse_error::create(115, chars_read,
11378 exception_message(input_format,
11379 concat("invalid number text: ",
11380 number_lexer.get_token_string()),
11381 "high-precision number"),
11382 nullptr));
11383 }
11384
11385 switch (result_number) {
11386 case token_type::value_integer:
11387 return sax->number_integer(number_lexer.get_number_integer());
11388 case token_type::value_unsigned:
11389 return sax->number_unsigned(number_lexer.get_number_unsigned());
11390 case token_type::value_float:
11391 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11392 case token_type::uninitialized:
11393 case token_type::literal_true:
11394 case token_type::literal_false:
11395 case token_type::literal_null:
11396 case token_type::value_string:
11397 case token_type::begin_array:
11398 case token_type::begin_object:
11399 case token_type::end_array:
11400 case token_type::end_object:
11401 case token_type::name_separator:
11402 case token_type::value_separator:
11403 case token_type::parse_error:
11404 case token_type::end_of_input:
11405 case token_type::literal_or_value:
11406 default:
11407 return sax->parse_error(
11408 chars_read, number_string,
11409 parse_error::create(115, chars_read,
11410 exception_message(input_format,
11411 concat("invalid number text: ",
11412 number_lexer.get_token_string()),
11413 "high-precision number"),
11414 nullptr));
11415 }
11416 }
11417
11419 // Utility functions //
11421
11431 char_int_type get() {
11432 ++chars_read;
11433 return current = ia.get_character();
11434 }
11435
11439 char_int_type get_ignore_noop() {
11440 do {
11441 get();
11442 } while (current == 'N');
11443
11444 return current;
11445 }
11446
11447 /*
11448 @brief read a number from the input
11449
11450 @tparam NumberType the type of the number
11451 @param[in] format the current format (for diagnostics)
11452 @param[out] result number of type @a NumberType
11453
11454 @return whether conversion completed
11455
11456 @note This function needs to respect the system's endianness, because
11457 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11458 (big endian) and therefore need reordering on little endian systems.
11459 On the other hand, BSON and BJData use little endian and should reorder
11460 on big endian systems.
11461 */
11462 template <typename NumberType, bool InputIsLittleEndian = false>
11463 bool get_number(const input_format_t format, NumberType& result) {
11464 // step 1: read input into array with system's byte order
11465 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11466 for (std::size_t i = 0; i < sizeof(NumberType); ++i) {
11467 get();
11468 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) {
11469 return false;
11470 }
11471
11472 // reverse byte order prior to conversion if necessary
11473 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) {
11474 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11475 } else {
11476 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11477 }
11478 }
11479
11480 // step 2: convert array into number of type T and return
11481 std::memcpy(&result, vec.data(), sizeof(NumberType));
11482 return true;
11483 }
11484
11499 template <typename NumberType>
11500 bool get_string(const input_format_t format, const NumberType len, string_t& result) {
11501 bool success = true;
11502 for (NumberType i = 0; i < len; i++) {
11503 get();
11504 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) {
11505 success = false;
11506 break;
11507 }
11508 result.push_back(static_cast<typename string_t::value_type>(current));
11509 }
11510 return success;
11511 }
11512
11527 template <typename NumberType>
11528 bool get_binary(const input_format_t format, const NumberType len, binary_t& result) {
11529 bool success = true;
11530 for (NumberType i = 0; i < len; i++) {
11531 get();
11532 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) {
11533 success = false;
11534 break;
11535 }
11536 result.push_back(static_cast<std::uint8_t>(current));
11537 }
11538 return success;
11539 }
11540
11546 JSON_HEDLEY_NON_NULL(3)
11547 bool unexpect_eof(const input_format_t format, const char* context) const {
11548 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) {
11549 return sax->parse_error(
11550 chars_read, "<end of file>",
11551 parse_error::create(110, chars_read,
11552 exception_message(format, "unexpected end of input", context),
11553 nullptr));
11554 }
11555 return true;
11556 }
11557
11561 std::string get_token_string() const {
11562 std::array<char, 3> cr{{}};
11563 static_cast<void>((std::snprintf)(
11564 cr.data(), cr.size(), "%.2hhX",
11565 static_cast<unsigned char>(
11566 current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11567 return std::string{cr.data()};
11568 }
11569
11576 std::string exception_message(const input_format_t format, const std::string& detail,
11577 const std::string& context) const {
11578 std::string error_msg = "syntax error while parsing ";
11579
11580 switch (format) {
11581 case input_format_t::cbor:
11582 error_msg += "CBOR";
11583 break;
11584
11585 case input_format_t::msgpack:
11586 error_msg += "MessagePack";
11587 break;
11588
11589 case input_format_t::ubjson:
11590 error_msg += "UBJSON";
11591 break;
11592
11593 case input_format_t::bson:
11594 error_msg += "BSON";
11595 break;
11596
11597 case input_format_t::bjdata:
11598 error_msg += "BJData";
11599 break;
11600
11601 case input_format_t::json: // LCOV_EXCL_LINE
11602 default: // LCOV_EXCL_LINE
11603 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
11604 // LCOV_EXCL_LINE
11605 }
11606
11607 return concat(error_msg, ' ', context, ": ", detail);
11608 }
11609
11610 private:
11611 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
11612
11614 InputAdapterType ia;
11615
11617 char_int_type current = char_traits<char_type>::eof();
11618
11620 std::size_t chars_read = 0;
11621
11623 const bool is_little_endian = little_endianness();
11624
11626 const input_format_t input_format = input_format_t::json;
11627
11629 json_sax_t* sax = nullptr;
11630
11631 // excluded markers in bjdata optimized type
11632#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
11633 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
11634
11635#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
11636 make_array<bjd_type>(bjd_type{'C', "char"}, bjd_type{'D', "double"}, bjd_type{'I', "int16"}, \
11637 bjd_type{'L', "int64"}, bjd_type{'M', "uint64"}, bjd_type{'U', "uint8"}, \
11638 bjd_type{'d', "single"}, bjd_type{'i', "int8"}, bjd_type{'l', "int32"}, \
11639 bjd_type{'m', "uint32"}, bjd_type{'u', "uint16"})
11640
11641 JSON_PRIVATE_UNLESS_TESTED :
11642 // lookup tables
11643 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
11644 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_)
11645 bjd_optimized_type_markers = JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
11646
11647 using bjd_type = std::pair<char_int_type, string_t>;
11648 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
11649 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
11650 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
11651
11652#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
11653#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
11654};
11655
11656#ifndef JSON_HAS_CPP_17
11657template <typename BasicJsonType, typename InputAdapterType, typename SAX>
11658constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
11659#endif
11660
11661} // namespace detail
11662NLOHMANN_JSON_NAMESPACE_END
11663
11664// #include <nlohmann/detail/input/input_adapters.hpp>
11665
11666// #include <nlohmann/detail/input/lexer.hpp>
11667
11668// #include <nlohmann/detail/input/parser.hpp>
11669// __ _____ _____ _____
11670// __| | __| | | | JSON for Modern C++
11671// | | |__ | | | | | | version 3.11.3
11672// |_____|_____|_____|_|___| https://github.com/nlohmann/json
11673//
11674// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
11675// SPDX-License-Identifier: MIT
11676
11677#include <cmath> // isfinite
11678#include <cstdint> // uint8_t
11679#include <functional> // function
11680#include <string> // string
11681#include <utility> // move
11682#include <vector> // vector
11683
11684// #include <nlohmann/detail/exceptions.hpp>
11685
11686// #include <nlohmann/detail/input/input_adapters.hpp>
11687
11688// #include <nlohmann/detail/input/json_sax.hpp>
11689
11690// #include <nlohmann/detail/input/lexer.hpp>
11691
11692// #include <nlohmann/detail/macro_scope.hpp>
11693
11694// #include <nlohmann/detail/meta/is_sax.hpp>
11695
11696// #include <nlohmann/detail/string_concat.hpp>
11697
11698// #include <nlohmann/detail/value_t.hpp>
11699
11700NLOHMANN_JSON_NAMESPACE_BEGIN
11701namespace detail {
11703// parser //
11705
11720
11721template <typename BasicJsonType>
11722using parser_callback_t =
11723 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
11724
11730template <typename BasicJsonType, typename InputAdapterType> class parser {
11731 using number_integer_t = typename BasicJsonType::number_integer_t;
11732 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
11733 using number_float_t = typename BasicJsonType::number_float_t;
11734 using string_t = typename BasicJsonType::string_t;
11736 using token_type = typename lexer_t::token_type;
11737
11738 public:
11740 explicit parser(InputAdapterType&& adapter, const parser_callback_t<BasicJsonType> cb = nullptr,
11741 const bool allow_exceptions_ = true, const bool skip_comments = false)
11742 : callback(cb), m_lexer(std::move(adapter), skip_comments),
11743 allow_exceptions(allow_exceptions_) {
11744 // read first token
11745 get_token();
11746 }
11747
11758 void parse(const bool strict, BasicJsonType& result) {
11759 if (callback) {
11760 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
11761 sax_parse_internal(&sdp);
11762
11763 // in strict mode, input must be completely read
11764 if (strict && (get_token() != token_type::end_of_input)) {
11765 sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
11767 101, m_lexer.get_position(),
11768 exception_message(token_type::end_of_input, "value"), nullptr));
11769 }
11770
11771 // in case of an error, return discarded value
11772 if (sdp.is_errored()) {
11773 result = value_t::discarded;
11774 return;
11775 }
11776
11777 // set top-level value to null if it was discarded by the callback
11778 // function
11779 if (result.is_discarded()) {
11780 result = nullptr;
11781 }
11782 } else {
11783 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
11784 sax_parse_internal(&sdp);
11785
11786 // in strict mode, input must be completely read
11787 if (strict && (get_token() != token_type::end_of_input)) {
11788 sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
11790 101, m_lexer.get_position(),
11791 exception_message(token_type::end_of_input, "value"), nullptr));
11792 }
11793
11794 // in case of an error, return discarded value
11795 if (sdp.is_errored()) {
11796 result = value_t::discarded;
11797 return;
11798 }
11799 }
11800
11801 result.assert_invariant();
11802 }
11803
11810 bool accept(const bool strict = true) {
11812 return sax_parse(&sax_acceptor, strict);
11813 }
11814
11815 template <typename SAX>
11816 JSON_HEDLEY_NON_NULL(2)
11817 bool sax_parse(SAX* sax, const bool strict = true) {
11819 const bool result = sax_parse_internal(sax);
11820
11821 // strict mode: next byte must be EOF
11822 if (result && strict && (get_token() != token_type::end_of_input)) {
11823 return sax->parse_error(
11824 m_lexer.get_position(), m_lexer.get_token_string(),
11825 parse_error::create(101, m_lexer.get_position(),
11826 exception_message(token_type::end_of_input, "value"), nullptr));
11827 }
11828
11829 return result;
11830 }
11831
11832 private:
11833 template <typename SAX> JSON_HEDLEY_NON_NULL(2) bool sax_parse_internal(SAX* sax) {
11834 // stack to remember the hierarchy of structured values we are parsing
11835 // true = array; false = object
11836 std::vector<bool> states;
11837 // value to avoid a goto (see comment where set to true)
11838 bool skip_to_state_evaluation = false;
11839
11840 while (true) {
11841 if (!skip_to_state_evaluation) {
11842 // invariant: get_token() was called before each iteration
11843 switch (last_token) {
11844 case token_type::begin_object: {
11845 if (JSON_HEDLEY_UNLIKELY(
11846 !sax->start_object(static_cast<std::size_t>(-1)))) {
11847 return false;
11848 }
11849
11850 // closing } -> we are done
11851 if (get_token() == token_type::end_object) {
11852 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
11853 return false;
11854 }
11855 break;
11856 }
11857
11858 // parse key
11859 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) {
11860 return sax->parse_error(
11861 m_lexer.get_position(), m_lexer.get_token_string(),
11862 parse_error::create(
11863 101, m_lexer.get_position(),
11864 exception_message(token_type::value_string, "object key"),
11865 nullptr));
11866 }
11867 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
11868 return false;
11869 }
11870
11871 // parse separator (:)
11872 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
11873 return sax->parse_error(
11874 m_lexer.get_position(), m_lexer.get_token_string(),
11875 parse_error::create(101, m_lexer.get_position(),
11876 exception_message(token_type::name_separator,
11877 "object separator"),
11878 nullptr));
11879 }
11880
11881 // remember we are now inside an object
11882 states.push_back(false);
11883
11884 // parse values
11885 get_token();
11886 continue;
11887 }
11888
11889 case token_type::begin_array: {
11890 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) {
11891 return false;
11892 }
11893
11894 // closing ] -> we are done
11895 if (get_token() == token_type::end_array) {
11896 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
11897 return false;
11898 }
11899 break;
11900 }
11901
11902 // remember we are now inside an array
11903 states.push_back(true);
11904
11905 // parse values (no need to call get_token)
11906 continue;
11907 }
11908
11909 case token_type::value_float: {
11910 const auto res = m_lexer.get_number_float();
11911
11912 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) {
11913 return sax->parse_error(
11914 m_lexer.get_position(), m_lexer.get_token_string(),
11915 out_of_range::create(406,
11916 concat("number overflow parsing '",
11917 m_lexer.get_token_string(), '\''),
11918 nullptr));
11919 }
11920
11921 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) {
11922 return false;
11923 }
11924
11925 break;
11926 }
11927
11928 case token_type::literal_false: {
11929 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) {
11930 return false;
11931 }
11932 break;
11933 }
11934
11935 case token_type::literal_null: {
11936 if (JSON_HEDLEY_UNLIKELY(!sax->null())) {
11937 return false;
11938 }
11939 break;
11940 }
11941
11942 case token_type::literal_true: {
11943 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) {
11944 return false;
11945 }
11946 break;
11947 }
11948
11949 case token_type::value_integer: {
11950 if (JSON_HEDLEY_UNLIKELY(
11951 !sax->number_integer(m_lexer.get_number_integer()))) {
11952 return false;
11953 }
11954 break;
11955 }
11956
11957 case token_type::value_string: {
11958 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) {
11959 return false;
11960 }
11961 break;
11962 }
11963
11964 case token_type::value_unsigned: {
11965 if (JSON_HEDLEY_UNLIKELY(
11966 !sax->number_unsigned(m_lexer.get_number_unsigned()))) {
11967 return false;
11968 }
11969 break;
11970 }
11971
11972 case token_type::parse_error: {
11973 // using "uninitialized" to avoid "expected" message
11974 return sax->parse_error(
11975 m_lexer.get_position(), m_lexer.get_token_string(),
11976 parse_error::create(
11977 101, m_lexer.get_position(),
11978 exception_message(token_type::uninitialized, "value"), nullptr));
11979 }
11980 case token_type::end_of_input: {
11981 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) {
11982 return sax->parse_error(
11983 m_lexer.get_position(), m_lexer.get_token_string(),
11984 parse_error::create(
11985 101, m_lexer.get_position(),
11986 "attempting to parse an empty input; check that your input "
11987 "string or stream contains the expected JSON",
11988 nullptr));
11989 }
11990
11991 return sax->parse_error(
11992 m_lexer.get_position(), m_lexer.get_token_string(),
11993 parse_error::create(
11994 101, m_lexer.get_position(),
11995 exception_message(token_type::literal_or_value, "value"), nullptr));
11996 }
11997 case token_type::uninitialized:
11998 case token_type::end_array:
11999 case token_type::end_object:
12000 case token_type::name_separator:
12001 case token_type::value_separator:
12002 case token_type::literal_or_value:
12003 default: // the last token was unexpected
12004 {
12005 return sax->parse_error(
12006 m_lexer.get_position(), m_lexer.get_token_string(),
12007 parse_error::create(
12008 101, m_lexer.get_position(),
12009 exception_message(token_type::literal_or_value, "value"), nullptr));
12010 }
12011 }
12012 } else {
12013 skip_to_state_evaluation = false;
12014 }
12015
12016 // we reached this line after we successfully parsed a value
12017 if (states.empty()) {
12018 // empty stack: we reached the end of the hierarchy: done
12019 return true;
12020 }
12021
12022 if (states.back()) // array
12023 {
12024 // comma -> next value
12025 if (get_token() == token_type::value_separator) {
12026 // parse a new value
12027 get_token();
12028 continue;
12029 }
12030
12031 // closing ]
12032 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) {
12033 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) {
12034 return false;
12035 }
12036
12037 // We are done with this array. Before we can parse a
12038 // new value, we need to evaluate the new state first.
12039 // By setting skip_to_state_evaluation to false, we
12040 // are effectively jumping to the beginning of this if.
12041 JSON_ASSERT(!states.empty());
12042 states.pop_back();
12043 skip_to_state_evaluation = true;
12044 continue;
12045 }
12046
12047 return sax->parse_error(
12048 m_lexer.get_position(), m_lexer.get_token_string(),
12049 parse_error::create(101, m_lexer.get_position(),
12050 exception_message(token_type::end_array, "array"),
12051 nullptr));
12052 }
12053
12054 // states.back() is false -> object
12055
12056 // comma -> next value
12057 if (get_token() == token_type::value_separator) {
12058 // parse key
12059 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) {
12060 return sax->parse_error(
12061 m_lexer.get_position(), m_lexer.get_token_string(),
12062 parse_error::create(
12063 101, m_lexer.get_position(),
12064 exception_message(token_type::value_string, "object key"), nullptr));
12065 }
12066
12067 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) {
12068 return false;
12069 }
12070
12071 // parse separator (:)
12072 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) {
12073 return sax->parse_error(
12074 m_lexer.get_position(), m_lexer.get_token_string(),
12075 parse_error::create(
12076 101, m_lexer.get_position(),
12077 exception_message(token_type::name_separator, "object separator"),
12078 nullptr));
12079 }
12080
12081 // parse values
12082 get_token();
12083 continue;
12084 }
12085
12086 // closing }
12087 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) {
12088 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) {
12089 return false;
12090 }
12091
12092 // We are done with this object. Before we can parse a
12093 // new value, we need to evaluate the new state first.
12094 // By setting skip_to_state_evaluation to false, we
12095 // are effectively jumping to the beginning of this if.
12096 JSON_ASSERT(!states.empty());
12097 states.pop_back();
12098 skip_to_state_evaluation = true;
12099 continue;
12100 }
12101
12102 return sax->parse_error(
12103 m_lexer.get_position(), m_lexer.get_token_string(),
12104 parse_error::create(101, m_lexer.get_position(),
12105 exception_message(token_type::end_object, "object"), nullptr));
12106 }
12107 }
12108
12110 token_type get_token() { return last_token = m_lexer.scan(); }
12111
12112 std::string exception_message(const token_type expected, const std::string& context) {
12113 std::string error_msg = "syntax error ";
12114
12115 if (!context.empty()) {
12116 error_msg += concat("while parsing ", context, ' ');
12117 }
12118
12119 error_msg += "- ";
12120
12121 if (last_token == token_type::parse_error) {
12122 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12123 m_lexer.get_token_string(), '\'');
12124 } else {
12125 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12126 }
12127
12128 if (expected != token_type::uninitialized) {
12129 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12130 }
12131
12132 return error_msg;
12133 }
12134
12135 private:
12137 const parser_callback_t<BasicJsonType> callback = nullptr;
12139 token_type last_token = token_type::uninitialized;
12141 lexer_t m_lexer;
12143 const bool allow_exceptions = true;
12144};
12145
12146} // namespace detail
12147NLOHMANN_JSON_NAMESPACE_END
12148
12149// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12150// __ _____ _____ _____
12151// __| | __| | | | JSON for Modern C++
12152// | | |__ | | | | | | version 3.11.3
12153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12154//
12155// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12156// SPDX-License-Identifier: MIT
12157
12158// #include <nlohmann/detail/abi_macros.hpp>
12159
12160// #include <nlohmann/detail/iterators/primitive_iterator.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#include <cstddef> // ptrdiff_t
12170#include <limits> // numeric_limits
12171
12172// #include <nlohmann/detail/macro_scope.hpp>
12173
12174NLOHMANN_JSON_NAMESPACE_BEGIN
12175namespace detail {
12176
12177/*
12178@brief an iterator for primitive JSON types
12179
12180This class models an iterator for primitive JSON types (boolean, number,
12181string). It's only purpose is to allow the iterator/const_iterator classes
12182to "iterate" over primitive values. Internally, the iterator is modeled by
12183a `difference_type` variable. Value begin_value (`0`) models the begin,
12184end_value (`1`) models past the end.
12185*/
12187 private:
12188 using difference_type = std::ptrdiff_t;
12189 static constexpr difference_type begin_value = 0;
12190 static constexpr difference_type end_value = begin_value + 1;
12191
12192 JSON_PRIVATE_UNLESS_TESTED :
12194 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12195
12196 public:
12197 constexpr difference_type get_value() const noexcept { return m_it; }
12198
12200 void set_begin() noexcept { m_it = begin_value; }
12201
12203 void set_end() noexcept { m_it = end_value; }
12204
12206 constexpr bool is_begin() const noexcept { return m_it == begin_value; }
12207
12209 constexpr bool is_end() const noexcept { return m_it == end_value; }
12210
12211 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept {
12212 return lhs.m_it == rhs.m_it;
12213 }
12214
12215 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept {
12216 return lhs.m_it < rhs.m_it;
12217 }
12218
12219 primitive_iterator_t operator+(difference_type n) noexcept {
12220 auto result = *this;
12221 result += n;
12222 return result;
12223 }
12224
12225 friend constexpr difference_type operator-(primitive_iterator_t lhs,
12226 primitive_iterator_t rhs) noexcept {
12227 return lhs.m_it - rhs.m_it;
12228 }
12229
12230 primitive_iterator_t& operator++() noexcept {
12231 ++m_it;
12232 return *this;
12233 }
12234
12235 primitive_iterator_t operator++(int) & noexcept // NOLINT(cert-dcl21-cpp)
12236 {
12237 auto result = *this;
12238 ++m_it;
12239 return result;
12240 }
12241
12242 primitive_iterator_t& operator--() noexcept {
12243 --m_it;
12244 return *this;
12245 }
12246
12247 primitive_iterator_t operator--(int) & noexcept // NOLINT(cert-dcl21-cpp)
12248 {
12249 auto result = *this;
12250 --m_it;
12251 return result;
12252 }
12253
12254 primitive_iterator_t& operator+=(difference_type n) noexcept {
12255 m_it += n;
12256 return *this;
12257 }
12258
12259 primitive_iterator_t& operator-=(difference_type n) noexcept {
12260 m_it -= n;
12261 return *this;
12262 }
12263};
12264
12265} // namespace detail
12266NLOHMANN_JSON_NAMESPACE_END
12267
12268NLOHMANN_JSON_NAMESPACE_BEGIN
12269namespace detail {
12270
12278template <typename BasicJsonType> struct internal_iterator {
12280 typename BasicJsonType::object_t::iterator object_iterator{};
12282 typename BasicJsonType::array_t::iterator array_iterator{};
12285};
12286
12287} // namespace detail
12288NLOHMANN_JSON_NAMESPACE_END
12289
12290// #include <nlohmann/detail/iterators/iter_impl.hpp>
12291// __ _____ _____ _____
12292// __| | __| | | | JSON for Modern C++
12293// | | |__ | | | | | | version 3.11.3
12294// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12295//
12296// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12297// SPDX-License-Identifier: MIT
12298
12299#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12300#include <type_traits> // conditional, is_const, remove_const
12301
12302// #include <nlohmann/detail/exceptions.hpp>
12303
12304// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12305
12306// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12307
12308// #include <nlohmann/detail/macro_scope.hpp>
12309
12310// #include <nlohmann/detail/meta/cpp_future.hpp>
12311
12312// #include <nlohmann/detail/meta/type_traits.hpp>
12313
12314// #include <nlohmann/detail/value_t.hpp>
12315
12316NLOHMANN_JSON_NAMESPACE_BEGIN
12317namespace detail {
12318
12319// forward declare, to be able to friend it later on
12320template <typename IteratorType> class iteration_proxy;
12321template <typename IteratorType> class iteration_proxy_value;
12322
12341template <typename BasicJsonType>
12342class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12343{
12345 using other_iter_impl =
12346 iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value,
12347 typename std::remove_const<BasicJsonType>::type,
12348 const BasicJsonType>::type>;
12350 friend other_iter_impl;
12351 friend BasicJsonType;
12354
12355 using object_t = typename BasicJsonType::object_t;
12356 using array_t = typename BasicJsonType::array_t;
12357 // make sure BasicJsonType is basic_json or const basic_json
12359 "iter_impl only accepts (const) basic_json");
12360 // superficial check for the LegacyBidirectionalIterator named requirement
12361 static_assert(
12362 std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value &&
12363 std::is_base_of<std::bidirectional_iterator_tag,
12364 typename std::iterator_traits<
12365 typename array_t::iterator>::iterator_category>::value,
12366 "basic_json iterator assumes array and object type iterators satisfy the "
12367 "LegacyBidirectionalIterator named requirement.");
12368
12369 public:
12377 using iterator_category = std::bidirectional_iterator_tag;
12378
12380 using value_type = typename BasicJsonType::value_type;
12382 using difference_type = typename BasicJsonType::difference_type;
12384 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12385 typename BasicJsonType::const_pointer,
12386 typename BasicJsonType::pointer>::type;
12388 using reference = typename std::conditional<std::is_const<BasicJsonType>::value,
12389 typename BasicJsonType::const_reference,
12390 typename BasicJsonType::reference>::type;
12391
12392 iter_impl() = default;
12393 ~iter_impl() = default;
12394 iter_impl(iter_impl&&) noexcept = default;
12395 iter_impl& operator=(iter_impl&&) noexcept = default;
12396
12403 explicit iter_impl(pointer object) noexcept : m_object(object) {
12404 JSON_ASSERT(m_object != nullptr);
12405
12406 switch (m_object->m_data.m_type) {
12407 case value_t::object: {
12408 m_it.object_iterator = typename object_t::iterator();
12409 break;
12410 }
12411
12412 case value_t::array: {
12413 m_it.array_iterator = typename array_t::iterator();
12414 break;
12415 }
12416
12417 case value_t::null:
12418 case value_t::string:
12419 case value_t::boolean:
12423 case value_t::binary:
12424 case value_t::discarded:
12425 default: {
12426 m_it.primitive_iterator = primitive_iterator_t();
12427 break;
12428 }
12429 }
12430 }
12431
12440
12448 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
12449 : m_object(other.m_object), m_it(other.m_it) {}
12450
12457 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept {
12458 if (&other != this) {
12459 m_object = other.m_object;
12460 m_it = other.m_it;
12461 }
12462 return *this;
12463 }
12464
12470 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12471 : m_object(other.m_object), m_it(other.m_it) {}
12472
12479 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>&
12480 other) noexcept // NOLINT(cert-oop54-cpp)
12481 {
12482 m_object = other.m_object;
12483 m_it = other.m_it;
12484 return *this;
12485 }
12486
12487 JSON_PRIVATE_UNLESS_TESTED :
12492 void
12493 set_begin() noexcept {
12494 JSON_ASSERT(m_object != nullptr);
12495
12496 switch (m_object->m_data.m_type) {
12497 case value_t::object: {
12498 m_it.object_iterator = m_object->m_data.m_value.object->begin();
12499 break;
12500 }
12501
12502 case value_t::array: {
12503 m_it.array_iterator = m_object->m_data.m_value.array->begin();
12504 break;
12505 }
12506
12507 case value_t::null: {
12508 // set to end so begin()==end() is true: null is empty
12509 m_it.primitive_iterator.set_end();
12510 break;
12511 }
12512
12513 case value_t::string:
12514 case value_t::boolean:
12515 case value_t::number_integer:
12516 case value_t::number_unsigned:
12517 case value_t::number_float:
12518 case value_t::binary:
12519 case value_t::discarded:
12520 default: {
12521 m_it.primitive_iterator.set_begin();
12522 break;
12523 }
12524 }
12525 }
12526
12531 void set_end() noexcept {
12532 JSON_ASSERT(m_object != nullptr);
12533
12534 switch (m_object->m_data.m_type) {
12535 case value_t::object: {
12536 m_it.object_iterator = m_object->m_data.m_value.object->end();
12537 break;
12538 }
12539
12540 case value_t::array: {
12541 m_it.array_iterator = m_object->m_data.m_value.array->end();
12542 break;
12543 }
12544
12545 case value_t::null:
12546 case value_t::string:
12547 case value_t::boolean:
12551 case value_t::binary:
12552 case value_t::discarded:
12553 default: {
12554 m_it.primitive_iterator.set_end();
12555 break;
12556 }
12557 }
12558 }
12559
12560 public:
12566 JSON_ASSERT(m_object != nullptr);
12567
12568 switch (m_object->m_data.m_type) {
12569 case value_t::object: {
12570 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
12571 return m_it.object_iterator->second;
12572 }
12573
12574 case value_t::array: {
12575 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
12576 return *m_it.array_iterator;
12577 }
12578
12579 case value_t::null:
12580 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12581
12582 case value_t::string:
12583 case value_t::boolean:
12587 case value_t::binary:
12588 case value_t::discarded:
12589 default: {
12590 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
12591 return *m_object;
12592 }
12593
12594 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12595 }
12596 }
12597 }
12598
12604 JSON_ASSERT(m_object != nullptr);
12605
12606 switch (m_object->m_data.m_type) {
12607 case value_t::object: {
12608 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
12609 return &(m_it.object_iterator->second);
12610 }
12611
12612 case value_t::array: {
12613 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
12614 return &*m_it.array_iterator;
12615 }
12616
12617 case value_t::null:
12618 case value_t::string:
12619 case value_t::boolean:
12623 case value_t::binary:
12624 case value_t::discarded:
12625 default: {
12626 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) {
12627 return m_object;
12628 }
12629
12630 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12631 }
12632 }
12633 }
12634
12639 iter_impl operator++(int) & // NOLINT(cert-dcl21-cpp)
12640 {
12641 auto result = *this;
12642 ++(*this);
12643 return result;
12644 }
12645
12650 iter_impl& operator++() {
12651 JSON_ASSERT(m_object != nullptr);
12652
12653 switch (m_object->m_data.m_type) {
12654 case value_t::object: {
12655 std::advance(m_it.object_iterator, 1);
12656 break;
12657 }
12658
12659 case value_t::array: {
12660 std::advance(m_it.array_iterator, 1);
12661 break;
12662 }
12663
12664 case value_t::null:
12665 case value_t::string:
12666 case value_t::boolean:
12670 case value_t::binary:
12671 case value_t::discarded:
12672 default: {
12673 ++m_it.primitive_iterator;
12674 break;
12675 }
12676 }
12677
12678 return *this;
12679 }
12680
12685 iter_impl operator--(int) & // NOLINT(cert-dcl21-cpp)
12686 {
12687 auto result = *this;
12688 --(*this);
12689 return result;
12690 }
12691
12696 iter_impl& operator--() {
12697 JSON_ASSERT(m_object != nullptr);
12698
12699 switch (m_object->m_data.m_type) {
12700 case value_t::object: {
12701 std::advance(m_it.object_iterator, -1);
12702 break;
12703 }
12704
12705 case value_t::array: {
12706 std::advance(m_it.array_iterator, -1);
12707 break;
12708 }
12709
12710 case value_t::null:
12711 case value_t::string:
12712 case value_t::boolean:
12716 case value_t::binary:
12717 case value_t::discarded:
12718 default: {
12719 --m_it.primitive_iterator;
12720 break;
12721 }
12722 }
12723
12724 return *this;
12725 }
12726
12731 template <typename IterImpl,
12732 detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value ||
12733 std::is_same<IterImpl, other_iter_impl>::value),
12734 std::nullptr_t> = nullptr>
12735 bool operator==(const IterImpl& other) const {
12736 // if objects are not the same, the comparison is undefined
12737 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
12738 JSON_THROW(invalid_iterator::create(
12739 212, "cannot compare iterators of different containers", m_object));
12740 }
12741
12742 JSON_ASSERT(m_object != nullptr);
12743
12744 switch (m_object->m_data.m_type) {
12745 case value_t::object:
12746 return (m_it.object_iterator == other.m_it.object_iterator);
12747
12748 case value_t::array:
12749 return (m_it.array_iterator == other.m_it.array_iterator);
12750
12751 case value_t::null:
12752 case value_t::string:
12753 case value_t::boolean:
12757 case value_t::binary:
12758 case value_t::discarded:
12759 default:
12760 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
12761 }
12762 }
12763
12768 template <typename IterImpl,
12769 detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value ||
12770 std::is_same<IterImpl, other_iter_impl>::value),
12771 std::nullptr_t> = nullptr>
12772 bool operator!=(const IterImpl& other) const {
12773 return !operator==(other);
12774 }
12775
12780 bool operator<(const iter_impl& other) const {
12781 // if objects are not the same, the comparison is undefined
12782 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) {
12783 JSON_THROW(invalid_iterator::create(
12784 212, "cannot compare iterators of different containers", m_object));
12785 }
12786
12787 JSON_ASSERT(m_object != nullptr);
12788
12789 switch (m_object->m_data.m_type) {
12790 case value_t::object:
12791 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators",
12792 m_object));
12793
12794 case value_t::array:
12795 return (m_it.array_iterator < other.m_it.array_iterator);
12796
12797 case value_t::null:
12798 case value_t::string:
12799 case value_t::boolean:
12803 case value_t::binary:
12804 case value_t::discarded:
12805 default:
12806 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
12807 }
12808 }
12809
12814 bool operator<=(const iter_impl& other) const { return !other.operator<(*this); }
12815
12820 bool operator>(const iter_impl& other) const { return !operator<=(other); }
12821
12826 bool operator>=(const iter_impl& other) const { return !operator<(other); }
12827
12833 JSON_ASSERT(m_object != nullptr);
12834
12835 switch (m_object->m_data.m_type) {
12836 case value_t::object:
12837 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators",
12838 m_object));
12839
12840 case value_t::array: {
12841 std::advance(m_it.array_iterator, i);
12842 break;
12843 }
12844
12845 case value_t::null:
12846 case value_t::string:
12847 case value_t::boolean:
12851 case value_t::binary:
12852 case value_t::discarded:
12853 default: {
12854 m_it.primitive_iterator += i;
12855 break;
12856 }
12857 }
12858
12859 return *this;
12860 }
12861
12866 iter_impl& operator-=(difference_type i) { return operator+=(-i); }
12867
12872 iter_impl operator+(difference_type i) const {
12873 auto result = *this;
12874 result += i;
12875 return result;
12876 }
12877
12882 friend iter_impl operator+(difference_type i, const iter_impl& it) {
12883 auto result = it;
12884 result += i;
12885 return result;
12886 }
12887
12892 iter_impl operator-(difference_type i) const {
12893 auto result = *this;
12894 result -= i;
12895 return result;
12896 }
12897
12902 difference_type operator-(const iter_impl& other) const {
12903 JSON_ASSERT(m_object != nullptr);
12904
12905 switch (m_object->m_data.m_type) {
12906 case value_t::object:
12907 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators",
12908 m_object));
12909
12910 case value_t::array:
12911 return m_it.array_iterator - other.m_it.array_iterator;
12912
12913 case value_t::null:
12914 case value_t::string:
12915 case value_t::boolean:
12919 case value_t::binary:
12920 case value_t::discarded:
12921 default:
12922 return m_it.primitive_iterator - other.m_it.primitive_iterator;
12923 }
12924 }
12925
12931 JSON_ASSERT(m_object != nullptr);
12932
12933 switch (m_object->m_data.m_type) {
12934 case value_t::object:
12935 JSON_THROW(invalid_iterator::create(
12936 208, "cannot use operator[] for object iterators", m_object));
12937
12938 case value_t::array:
12939 return *std::next(m_it.array_iterator, n);
12940
12941 case value_t::null:
12942 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12943
12944 case value_t::string:
12945 case value_t::boolean:
12949 case value_t::binary:
12950 case value_t::discarded:
12951 default: {
12952 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) {
12953 return *m_object;
12954 }
12955
12956 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
12957 }
12958 }
12959 }
12960
12965 const typename object_t::key_type& key() const {
12966 JSON_ASSERT(m_object != nullptr);
12967
12968 if (JSON_HEDLEY_LIKELY(m_object->is_object())) {
12969 return m_it.object_iterator->first;
12970 }
12971
12972 JSON_THROW(
12973 invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
12974 }
12975
12980 reference value() const { return operator*(); }
12981
12982 JSON_PRIVATE_UNLESS_TESTED :
12984 pointer m_object = nullptr;
12987};
12988
12989} // namespace detail
12990NLOHMANN_JSON_NAMESPACE_END
12991
12992// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
12993
12994// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
12995// __ _____ _____ _____
12996// __| | __| | | | JSON for Modern C++
12997// | | |__ | | | | | | version 3.11.3
12998// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12999//
13000// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13001// SPDX-License-Identifier: MIT
13002
13003#include <cstddef> // ptrdiff_t
13004#include <iterator> // reverse_iterator
13005#include <utility> // declval
13006
13007// #include <nlohmann/detail/abi_macros.hpp>
13008
13009NLOHMANN_JSON_NAMESPACE_BEGIN
13010namespace detail {
13011
13013// reverse_iterator //
13015
13034template <typename Base> class json_reverse_iterator : public std::reverse_iterator<Base> {
13035 public:
13036 using difference_type = std::ptrdiff_t;
13038 using base_iterator = std::reverse_iterator<Base>;
13040 using reference = typename Base::reference;
13041
13043 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13044 : base_iterator(it) {}
13045
13047 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13048
13050 json_reverse_iterator operator++(int) & // NOLINT(cert-dcl21-cpp)
13051 {
13052 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13053 }
13054
13057 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13058 }
13059
13061 json_reverse_iterator operator--(int) & // NOLINT(cert-dcl21-cpp)
13062 {
13063 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13064 }
13065
13068 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13069 }
13070
13072 json_reverse_iterator& operator+=(difference_type i) {
13073 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13074 }
13075
13077 json_reverse_iterator operator+(difference_type i) const {
13078 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13079 }
13080
13082 json_reverse_iterator operator-(difference_type i) const {
13083 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13084 }
13085
13087 difference_type operator-(const json_reverse_iterator& other) const {
13088 return base_iterator(*this) - base_iterator(other);
13089 }
13090
13092 reference operator[](difference_type n) const { return *(this->operator+(n)); }
13093
13095 auto key() const -> decltype(std::declval<Base>().key()) {
13096 auto it = --this->base();
13097 return it.key();
13098 }
13099
13102 auto it = --this->base();
13103 return it.operator*();
13104 }
13105};
13106
13107} // namespace detail
13108NLOHMANN_JSON_NAMESPACE_END
13109
13110// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13111
13112// #include <nlohmann/detail/json_custom_base_class.hpp>
13113// __ _____ _____ _____
13114// __| | __| | | | JSON for Modern C++
13115// | | |__ | | | | | | version 3.11.3
13116// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13117//
13118// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13119// SPDX-License-Identifier: MIT
13120
13121#include <type_traits> // conditional, is_same
13122
13123// #include <nlohmann/detail/abi_macros.hpp>
13124
13125NLOHMANN_JSON_NAMESPACE_BEGIN
13126namespace detail {
13127
13139
13140template <class T>
13141using json_base_class =
13142 typename std::conditional<std::is_same<T, void>::value, json_default_base, T>::type;
13143
13144} // namespace detail
13145NLOHMANN_JSON_NAMESPACE_END
13146
13147// #include <nlohmann/detail/json_pointer.hpp>
13148// __ _____ _____ _____
13149// __| | __| | | | JSON for Modern C++
13150// | | |__ | | | | | | version 3.11.3
13151// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13152//
13153// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13154// SPDX-License-Identifier: MIT
13155
13156#include <algorithm> // all_of
13157#include <cctype> // isdigit
13158#include <cerrno> // errno, ERANGE
13159#include <cstdlib> // strtoull
13160#ifndef JSON_NO_IO
13161#include <iosfwd> // ostream
13162#endif // JSON_NO_IO
13163#include <limits> // max
13164#include <numeric> // accumulate
13165#include <string> // string
13166#include <utility> // move
13167#include <vector> // vector
13168
13169// #include <nlohmann/detail/exceptions.hpp>
13170
13171// #include <nlohmann/detail/macro_scope.hpp>
13172
13173// #include <nlohmann/detail/string_concat.hpp>
13174
13175// #include <nlohmann/detail/string_escape.hpp>
13176
13177// #include <nlohmann/detail/value_t.hpp>
13178
13179NLOHMANN_JSON_NAMESPACE_BEGIN
13180
13184template <typename RefStringType> class json_pointer {
13185 // allow basic_json to access private members
13186 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13187 friend class basic_json;
13188
13189 template <typename> friend class json_pointer;
13190
13191 template <typename T> struct string_t_helper {
13192 using type = T;
13193 };
13194
13195 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13196 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> {
13197 using type = StringType;
13198 };
13199
13200 public:
13201 // for backwards compatibility accept BasicJsonType
13202 using string_t = typename string_t_helper<RefStringType>::type;
13203
13206 explicit json_pointer(const string_t& s = "") : reference_tokens(split(s)) {}
13207
13210 string_t to_string() const {
13211 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), string_t{},
13212 [](const string_t& a, const string_t& b) {
13213 return detail::concat(a, '/', detail::escape(b));
13214 });
13215 }
13216
13219 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13220 operator string_t() const { return to_string(); }
13221
13222#ifndef JSON_NO_IO
13225 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) {
13226 o << ptr.to_string();
13227 return o;
13228 }
13229#endif
13230
13233 json_pointer& operator/=(const json_pointer& ptr) {
13234 reference_tokens.insert(reference_tokens.end(), ptr.reference_tokens.begin(),
13235 ptr.reference_tokens.end());
13236 return *this;
13237 }
13238
13241 json_pointer& operator/=(string_t token) {
13242 push_back(std::move(token));
13243 return *this;
13244 }
13245
13248 json_pointer& operator/=(std::size_t array_idx) { return *this /= std::to_string(array_idx); }
13249
13253 friend json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs) {
13254 return json_pointer(lhs) /= rhs;
13255 }
13256
13260 friend json_pointer operator/(const json_pointer& lhs,
13261 string_t token) // NOLINT(performance-unnecessary-value-param)
13262 {
13263 return json_pointer(lhs) /= std::move(token);
13264 }
13265
13269 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) {
13270 return json_pointer(lhs) /= array_idx;
13271 }
13272
13275 json_pointer parent_pointer() const {
13276 if (empty()) {
13277 return *this;
13278 }
13279
13280 json_pointer res = *this;
13281 res.pop_back();
13282 return res;
13283 }
13284
13287 void pop_back() {
13288 if (JSON_HEDLEY_UNLIKELY(empty())) {
13289 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13290 }
13291
13292 reference_tokens.pop_back();
13293 }
13294
13297 const string_t& back() const {
13298 if (JSON_HEDLEY_UNLIKELY(empty())) {
13299 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13300 }
13301
13302 return reference_tokens.back();
13303 }
13304
13307 void push_back(const string_t& token) { reference_tokens.push_back(token); }
13308
13311 void push_back(string_t&& token) { reference_tokens.push_back(std::move(token)); }
13312
13315 bool empty() const noexcept { return reference_tokens.empty(); }
13316
13317 private:
13328 template <typename BasicJsonType>
13329 static typename BasicJsonType::size_type array_index(const string_t& s) {
13330 using size_type = typename BasicJsonType::size_type;
13331
13332 // error condition (cf. RFC 6901, Sect. 4)
13333 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) {
13334 JSON_THROW(detail::parse_error::create(
13335 106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13336 }
13337
13338 // error condition (cf. RFC 6901, Sect. 4)
13339 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) {
13340 JSON_THROW(detail::parse_error::create(
13341 109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13342 }
13343
13344 const char* p = s.c_str();
13345 char* p_end = nullptr;
13346 errno = 0; // strtoull doesn't reset errno
13347 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13348 if (p == p_end // invalid input or empty string
13349 || errno == ERANGE // out of range
13350 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) !=
13351 s.size())) // incomplete read
13352 {
13353 JSON_THROW(detail::out_of_range::create(
13354 404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13355 }
13356
13357 // only triggered on special platforms (like 32bit), see also
13358 // https://github.com/nlohmann/json/pull/2203
13359 if (res >= static_cast<unsigned long long>(
13360 (std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13361 {
13362 JSON_THROW(detail::out_of_range::create(
13363 410, detail::concat("array index ", s, " exceeds size_type"),
13364 nullptr)); // LCOV_EXCL_LINE
13365 }
13366
13367 return static_cast<size_type>(res);
13368 }
13369
13370 JSON_PRIVATE_UNLESS_TESTED : json_pointer top() const {
13371 if (JSON_HEDLEY_UNLIKELY(empty())) {
13372 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13373 }
13374
13375 json_pointer result = *this;
13376 result.reference_tokens = {reference_tokens[0]};
13377 return result;
13378 }
13379
13380 private:
13389 template <typename BasicJsonType> BasicJsonType& get_and_create(BasicJsonType& j) const {
13390 auto* result = &j;
13391
13392 // in case no reference tokens exist, return a reference to the JSON value
13393 // j which will be overwritten by a primitive value
13394 for (const auto& reference_token : reference_tokens) {
13395 switch (result->type()) {
13396 case detail::value_t::null: {
13397 if (reference_token == "0") {
13398 // start a new array if reference token is 0
13399 result = &result->operator[](0);
13400 } else {
13401 // start a new object otherwise
13402 result = &result->operator[](reference_token);
13403 }
13404 break;
13405 }
13406
13408 // create an entry in the object
13409 result = &result->operator[](reference_token);
13410 break;
13411 }
13412
13414 // create an entry in the array
13415 result = &result->operator[](array_index<BasicJsonType>(reference_token));
13416 break;
13417 }
13418
13419 /*
13420 The following code is only reached if there exists a reference
13421 token _and_ the current value is primitive. In this case, we have
13422 an error situation, because primitive values may only occur as
13423 single value; that is, with an empty list of reference tokens.
13424 */
13432 default:
13433 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
13434 }
13435 }
13436
13437 return *result;
13438 }
13439
13459 template <typename BasicJsonType> BasicJsonType& get_unchecked(BasicJsonType* ptr) const {
13460 for (const auto& reference_token : reference_tokens) {
13461 // convert null values to arrays or objects before continuing
13462 if (ptr->is_null()) {
13463 // check if reference token is a number
13464 const bool nums =
13465 std::all_of(reference_token.begin(), reference_token.end(),
13466 [](const unsigned char x) { return std::isdigit(x); });
13467
13468 // change value to array for numbers or "-" or to object otherwise
13469 *ptr = (nums || reference_token == "-") ? detail::value_t::array
13470 : detail::value_t::object;
13471 }
13472
13473 switch (ptr->type()) {
13475 // use unchecked object access
13476 ptr = &ptr->operator[](reference_token);
13477 break;
13478 }
13479
13481 if (reference_token == "-") {
13482 // explicitly treat "-" as index beyond the end
13483 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
13484 } else {
13485 // convert array index to number; unchecked access
13486 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13487 }
13488 break;
13489 }
13490
13499 default:
13500 JSON_THROW(detail::out_of_range::create(
13501 404, detail::concat("unresolved reference token '", reference_token, "'"),
13502 ptr));
13503 }
13504 }
13505
13506 return *ptr;
13507 }
13508
13515 template <typename BasicJsonType> BasicJsonType& get_checked(BasicJsonType* ptr) const {
13516 for (const auto& reference_token : reference_tokens) {
13517 switch (ptr->type()) {
13519 // note: at performs range check
13520 ptr = &ptr->at(reference_token);
13521 break;
13522 }
13523
13525 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
13526 // "-" always fails the range check
13527 JSON_THROW(detail::out_of_range::create(
13528 402,
13529 detail::concat("array index '-' (",
13530 std::to_string(ptr->m_data.m_value.array->size()),
13531 ") is out of range"),
13532 ptr));
13533 }
13534
13535 // note: at performs range check
13536 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13537 break;
13538 }
13539
13548 default:
13549 JSON_THROW(detail::out_of_range::create(
13550 404, detail::concat("unresolved reference token '", reference_token, "'"),
13551 ptr));
13552 }
13553 }
13554
13555 return *ptr;
13556 }
13557
13571 template <typename BasicJsonType>
13572 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const {
13573 for (const auto& reference_token : reference_tokens) {
13574 switch (ptr->type()) {
13576 // use unchecked object access
13577 ptr = &ptr->operator[](reference_token);
13578 break;
13579 }
13580
13582 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
13583 // "-" cannot be used for const access
13584 JSON_THROW(detail::out_of_range::create(
13585 402,
13586 detail::concat("array index '-' (",
13587 std::to_string(ptr->m_data.m_value.array->size()),
13588 ") is out of range"),
13589 ptr));
13590 }
13591
13592 // use unchecked array access
13593 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
13594 break;
13595 }
13596
13605 default:
13606 JSON_THROW(detail::out_of_range::create(
13607 404, detail::concat("unresolved reference token '", reference_token, "'"),
13608 ptr));
13609 }
13610 }
13611
13612 return *ptr;
13613 }
13614
13621 template <typename BasicJsonType>
13622 const BasicJsonType& get_checked(const BasicJsonType* ptr) const {
13623 for (const auto& reference_token : reference_tokens) {
13624 switch (ptr->type()) {
13626 // note: at performs range check
13627 ptr = &ptr->at(reference_token);
13628 break;
13629 }
13630
13632 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
13633 // "-" always fails the range check
13634 JSON_THROW(detail::out_of_range::create(
13635 402,
13636 detail::concat("array index '-' (",
13637 std::to_string(ptr->m_data.m_value.array->size()),
13638 ") is out of range"),
13639 ptr));
13640 }
13641
13642 // note: at performs range check
13643 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
13644 break;
13645 }
13646
13655 default:
13656 JSON_THROW(detail::out_of_range::create(
13657 404, detail::concat("unresolved reference token '", reference_token, "'"),
13658 ptr));
13659 }
13660 }
13661
13662 return *ptr;
13663 }
13664
13669 template <typename BasicJsonType> bool contains(const BasicJsonType* ptr) const {
13670 for (const auto& reference_token : reference_tokens) {
13671 switch (ptr->type()) {
13673 if (!ptr->contains(reference_token)) {
13674 // we did not find the key in the object
13675 return false;
13676 }
13677
13678 ptr = &ptr->operator[](reference_token);
13679 break;
13680 }
13681
13683 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) {
13684 // "-" always fails the range check
13685 return false;
13686 }
13687 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 &&
13688 !("0" <= reference_token && reference_token <= "9"))) {
13689 // invalid char
13690 return false;
13691 }
13692 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) {
13693 if (JSON_HEDLEY_UNLIKELY(
13694 !('1' <= reference_token[0] && reference_token[0] <= '9'))) {
13695 // first char should be between '1' and '9'
13696 return false;
13697 }
13698 for (std::size_t i = 1; i < reference_token.size(); i++) {
13699 if (JSON_HEDLEY_UNLIKELY(
13700 !('0' <= reference_token[i] && reference_token[i] <= '9'))) {
13701 // other char should be between '0' and '9'
13702 return false;
13703 }
13704 }
13705 }
13706
13707 const auto idx = array_index<BasicJsonType>(reference_token);
13708 if (idx >= ptr->size()) {
13709 // index out of range
13710 return false;
13711 }
13712
13713 ptr = &ptr->operator[](idx);
13714 break;
13715 }
13716
13725 default: {
13726 // we do not expect primitive values if there is still a
13727 // reference token to process
13728 return false;
13729 }
13730 }
13731 }
13732
13733 // no reference token left means we found a primitive value
13734 return true;
13735 }
13736
13746 static std::vector<string_t> split(const string_t& reference_string) {
13747 std::vector<string_t> result;
13748
13749 // special case: empty reference string -> no reference tokens
13750 if (reference_string.empty()) {
13751 return result;
13752 }
13753
13754 // check if nonempty reference string begins with slash
13755 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) {
13756 JSON_THROW(detail::parse_error::create(
13757 107, 1,
13758 detail::concat("JSON pointer must be empty or begin with '/' - was: '",
13759 reference_string, "'"),
13760 nullptr));
13761 }
13762
13763 // extract the reference tokens:
13764 // - slash: position of the last read slash (or end of string)
13765 // - start: position after the previous slash
13766 for (
13767 // search for the first slash after the first character
13768 std::size_t slash = reference_string.find_first_of('/', 1),
13769 // set the beginning of the first reference token
13770 start = 1;
13771 // we can stop if start == 0 (if slash == string_t::npos)
13772 start != 0;
13773 // set the beginning of the next reference token
13774 // (will eventually be 0 if slash == string_t::npos)
13775 start = (slash == string_t::npos) ? 0 : slash + 1,
13776 // find next slash
13777 slash = reference_string.find_first_of('/', start)) {
13778 // use the text between the beginning of the reference token
13779 // (start) and the last slash (slash).
13780 auto reference_token = reference_string.substr(start, slash - start);
13781
13782 // check reference tokens are properly escaped
13783 for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos;
13784 pos = reference_token.find_first_of('~', pos + 1)) {
13785 JSON_ASSERT(reference_token[pos] == '~');
13786
13787 // ~ must be followed by 0 or 1
13788 if (JSON_HEDLEY_UNLIKELY(
13789 pos == reference_token.size() - 1 ||
13790 (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) {
13791 JSON_THROW(detail::parse_error::create(
13792 108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
13793 }
13794 }
13795
13796 // finally, store the reference token
13797 detail::unescape(reference_token);
13798 result.push_back(reference_token);
13799 }
13800
13801 return result;
13802 }
13803
13804 private:
13812 template <typename BasicJsonType>
13813 static void flatten(const string_t& reference_string, const BasicJsonType& value,
13814 BasicJsonType& result) {
13815 switch (value.type()) {
13817 if (value.m_data.m_value.array->empty()) {
13818 // flatten empty array as null
13819 result[reference_string] = nullptr;
13820 } else {
13821 // iterate array and use index as reference string
13822 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) {
13823 flatten(detail::concat(reference_string, '/', std::to_string(i)),
13824 value.m_data.m_value.array->operator[](i), result);
13825 }
13826 }
13827 break;
13828 }
13829
13831 if (value.m_data.m_value.object->empty()) {
13832 // flatten empty object as null
13833 result[reference_string] = nullptr;
13834 } else {
13835 // iterate object and use keys as reference string
13836 for (const auto& element : *value.m_data.m_value.object) {
13837 flatten(
13838 detail::concat(reference_string, '/', detail::escape(element.first)),
13839 element.second, result);
13840 }
13841 }
13842 break;
13843 }
13844
13853 default: {
13854 // add primitive value with its reference string
13855 result[reference_string] = value;
13856 break;
13857 }
13858 }
13859 }
13860
13871 template <typename BasicJsonType> static BasicJsonType unflatten(const BasicJsonType& value) {
13872 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) {
13873 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
13874 }
13875
13876 BasicJsonType result;
13877
13878 // iterate the JSON object values
13879 for (const auto& element : *value.m_data.m_value.object) {
13880 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) {
13881 JSON_THROW(detail::type_error::create(315, "values in object must be primitive",
13882 &element.second));
13883 }
13884
13885 // assign value to reference pointed to by JSON pointer; Note that if
13886 // the JSON pointer is "" (i.e., points to the whole value), function
13887 // get_and_create returns a reference to result itself. An assignment
13888 // will then create a primitive value.
13889 json_pointer(element.first).get_and_create(result) = element.second;
13890 }
13891
13892 return result;
13893 }
13894
13895 // can't use conversion operator because of ambiguity
13896 json_pointer<string_t> convert() const& {
13897 json_pointer<string_t> result;
13898 result.reference_tokens = reference_tokens;
13899 return result;
13900 }
13901
13902 json_pointer<string_t> convert() && {
13903 json_pointer<string_t> result;
13904 result.reference_tokens = std::move(reference_tokens);
13905 return result;
13906 }
13907
13908 public:
13909#if JSON_HAS_THREE_WAY_COMPARISON
13912 template <typename RefStringTypeRhs>
13913 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept {
13914 return reference_tokens == rhs.reference_tokens;
13915 }
13916
13919 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
13920 bool operator==(const string_t& rhs) const { return *this == json_pointer(rhs); }
13921
13923 template <typename RefStringTypeRhs>
13924 std::strong_ordering
13925 operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
13926 {
13927 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
13928 }
13929#else
13932 template <typename RefStringTypeLhs, typename RefStringTypeRhs>
13933 // NOLINTNEXTLINE(readability-redundant-declaration)
13934 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
13935 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
13936
13939 template <typename RefStringTypeLhs, typename StringType>
13940 // NOLINTNEXTLINE(readability-redundant-declaration)
13941 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
13942
13945 template <typename RefStringTypeRhs, typename StringType>
13946 // NOLINTNEXTLINE(readability-redundant-declaration)
13947 friend bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
13948
13951 template <typename RefStringTypeLhs, typename RefStringTypeRhs>
13952 // NOLINTNEXTLINE(readability-redundant-declaration)
13953 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
13954 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
13955
13958 template <typename RefStringTypeLhs, typename StringType>
13959 // NOLINTNEXTLINE(readability-redundant-declaration)
13960 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
13961
13964 template <typename RefStringTypeRhs, typename StringType>
13965 // NOLINTNEXTLINE(readability-redundant-declaration)
13966 friend bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
13967
13969 template <typename RefStringTypeLhs, typename RefStringTypeRhs>
13970 // NOLINTNEXTLINE(readability-redundant-declaration)
13971 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
13972 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
13973#endif
13974
13975 private:
13977 std::vector<string_t> reference_tokens;
13978};
13979
13980#if !JSON_HAS_THREE_WAY_COMPARISON
13981// functions cannot be defined inside class due to ODR violations
13982template <typename RefStringTypeLhs, typename RefStringTypeRhs>
13983inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
13984 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
13985 return lhs.reference_tokens == rhs.reference_tokens;
13986}
13987
13988template <typename RefStringTypeLhs,
13989 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
13990JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
13991inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs) {
13992 return lhs == json_pointer<RefStringTypeLhs>(rhs);
13993}
13994
13995template <typename RefStringTypeRhs,
13996 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
13997JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
13998inline bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs) {
13999 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14000}
14001
14002template <typename RefStringTypeLhs, typename RefStringTypeRhs>
14003inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14004 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
14005 return !(lhs == rhs);
14006}
14007
14008template <typename RefStringTypeLhs,
14009 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14010JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14011inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs) {
14012 return !(lhs == rhs);
14013}
14014
14015template <typename RefStringTypeRhs,
14016 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14017JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14018inline bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs) {
14019 return !(lhs == rhs);
14020}
14021
14022template <typename RefStringTypeLhs, typename RefStringTypeRhs>
14023inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14024 const json_pointer<RefStringTypeRhs>& rhs) noexcept {
14025 return lhs.reference_tokens < rhs.reference_tokens;
14026}
14027#endif
14028
14029NLOHMANN_JSON_NAMESPACE_END
14030
14031// #include <nlohmann/detail/json_ref.hpp>
14032// __ _____ _____ _____
14033// __| | __| | | | JSON for Modern C++
14034// | | |__ | | | | | | version 3.11.3
14035// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14036//
14037// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14038// SPDX-License-Identifier: MIT
14039
14040#include <initializer_list>
14041#include <utility>
14042
14043// #include <nlohmann/detail/abi_macros.hpp>
14044
14045// #include <nlohmann/detail/meta/type_traits.hpp>
14046
14047NLOHMANN_JSON_NAMESPACE_BEGIN
14048namespace detail {
14049
14050template <typename BasicJsonType> class json_ref {
14051 public:
14052 using value_type = BasicJsonType;
14053
14054 json_ref(value_type&& value) : owned_value(std::move(value)) {}
14055
14056 json_ref(const value_type& value) : value_ref(&value) {}
14057
14058 json_ref(std::initializer_list<json_ref> init) : owned_value(init) {}
14059
14060 template <class... Args,
14061 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0>
14062 json_ref(Args&&... args) : owned_value(std::forward<Args>(args)...) {}
14063
14064 // class should be movable only
14065 json_ref(json_ref&&) noexcept = default;
14066 json_ref(const json_ref&) = delete;
14067 json_ref& operator=(const json_ref&) = delete;
14068 json_ref& operator=(json_ref&&) = delete;
14069 ~json_ref() = default;
14070
14071 value_type moved_or_copied() const {
14072 if (value_ref == nullptr) {
14073 return std::move(owned_value);
14074 }
14075 return *value_ref;
14076 }
14077
14078 value_type const& operator*() const { return value_ref ? *value_ref : owned_value; }
14079
14080 value_type const* operator->() const { return &**this; }
14081
14082 private:
14083 mutable value_type owned_value = nullptr;
14084 value_type const* value_ref = nullptr;
14085};
14086
14087} // namespace detail
14088NLOHMANN_JSON_NAMESPACE_END
14089
14090// #include <nlohmann/detail/macro_scope.hpp>
14091
14092// #include <nlohmann/detail/string_concat.hpp>
14093
14094// #include <nlohmann/detail/string_escape.hpp>
14095
14096// #include <nlohmann/detail/meta/cpp_future.hpp>
14097
14098// #include <nlohmann/detail/meta/type_traits.hpp>
14099
14100// #include <nlohmann/detail/output/binary_writer.hpp>
14101// __ _____ _____ _____
14102// __| | __| | | | JSON for Modern C++
14103// | | |__ | | | | | | version 3.11.3
14104// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14105//
14106// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14107// SPDX-License-Identifier: MIT
14108
14109#include <algorithm> // reverse
14110#include <array> // array
14111#include <cmath> // isnan, isinf
14112#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14113#include <cstring> // memcpy
14114#include <limits> // numeric_limits
14115#include <map> // map
14116#include <string> // string
14117#include <utility> // move
14118#include <vector> // vector
14119
14120// #include <nlohmann/detail/input/binary_reader.hpp>
14121
14122// #include <nlohmann/detail/macro_scope.hpp>
14123
14124// #include <nlohmann/detail/output/output_adapters.hpp>
14125// __ _____ _____ _____
14126// __| | __| | | | JSON for Modern C++
14127// | | |__ | | | | | | version 3.11.3
14128// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14129//
14130// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14131// SPDX-License-Identifier: MIT
14132
14133#include <algorithm> // copy
14134#include <cstddef> // size_t
14135#include <iterator> // back_inserter
14136#include <memory> // shared_ptr, make_shared
14137#include <string> // basic_string
14138#include <vector> // vector
14139
14140#ifndef JSON_NO_IO
14141#include <ios> // streamsize
14142#include <ostream> // basic_ostream
14143#endif // JSON_NO_IO
14144
14145// #include <nlohmann/detail/macro_scope.hpp>
14146
14147NLOHMANN_JSON_NAMESPACE_BEGIN
14148namespace detail {
14149
14151template <typename CharType> struct output_adapter_protocol {
14152 virtual void write_character(CharType c) = 0;
14153 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14154 virtual ~output_adapter_protocol() = default;
14155
14156 output_adapter_protocol() = default;
14157 output_adapter_protocol(const output_adapter_protocol&) = default;
14158 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14159 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14160 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14161};
14162
14164template <typename CharType>
14165using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14166
14168template <typename CharType, typename AllocatorType = std::allocator<CharType>>
14169class output_vector_adapter : public output_adapter_protocol<CharType> {
14170 public:
14171 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept : v(vec) {}
14172
14173 void write_character(CharType c) override { v.push_back(c); }
14174
14175 JSON_HEDLEY_NON_NULL(2)
14176 void write_characters(const CharType* s, std::size_t length) override {
14177 v.insert(v.end(), s, s + length);
14178 }
14179
14180 private:
14181 std::vector<CharType, AllocatorType>& v;
14182};
14183
14184#ifndef JSON_NO_IO
14186template <typename CharType>
14187class output_stream_adapter : public output_adapter_protocol<CharType> {
14188 public:
14189 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept : stream(s) {}
14190
14191 void write_character(CharType c) override { stream.put(c); }
14192
14193 JSON_HEDLEY_NON_NULL(2)
14194 void write_characters(const CharType* s, std::size_t length) override {
14195 stream.write(s, static_cast<std::streamsize>(length));
14196 }
14197
14198 private:
14199 std::basic_ostream<CharType>& stream;
14200};
14201#endif // JSON_NO_IO
14202
14204template <typename CharType, typename StringType = std::basic_string<CharType>>
14205class output_string_adapter : public output_adapter_protocol<CharType> {
14206 public:
14207 explicit output_string_adapter(StringType& s) noexcept : str(s) {}
14208
14209 void write_character(CharType c) override { str.push_back(c); }
14210
14211 JSON_HEDLEY_NON_NULL(2)
14212 void write_characters(const CharType* s, std::size_t length) override { str.append(s, length); }
14213
14214 private:
14215 StringType& str;
14216};
14217
14218template <typename CharType, typename StringType = std::basic_string<CharType>>
14219class output_adapter {
14220 public:
14221 template <typename AllocatorType = std::allocator<CharType>>
14222 output_adapter(std::vector<CharType, AllocatorType>& vec)
14223 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14224
14225#ifndef JSON_NO_IO
14226 output_adapter(std::basic_ostream<CharType>& s)
14227 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14228#endif // JSON_NO_IO
14229
14230 output_adapter(StringType& s)
14231 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14232
14233 operator output_adapter_t<CharType>() { return oa; }
14234
14235 private:
14236 output_adapter_t<CharType> oa = nullptr;
14237};
14238
14239} // namespace detail
14240NLOHMANN_JSON_NAMESPACE_END
14241
14242// #include <nlohmann/detail/string_concat.hpp>
14243
14244NLOHMANN_JSON_NAMESPACE_BEGIN
14245namespace detail {
14246
14248// binary writer //
14250
14254template <typename BasicJsonType, typename CharType> class binary_writer {
14255 using string_t = typename BasicJsonType::string_t;
14256 using binary_t = typename BasicJsonType::binary_t;
14257 using number_float_t = typename BasicJsonType::number_float_t;
14258
14259 public:
14265 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) {
14266 JSON_ASSERT(oa);
14267 }
14268
14273 void write_bson(const BasicJsonType& j) {
14274 switch (j.type()) {
14275 case value_t::object: {
14276 write_bson_object(*j.m_data.m_value.object);
14277 break;
14278 }
14279
14280 case value_t::null:
14281 case value_t::array:
14282 case value_t::string:
14283 case value_t::boolean:
14287 case value_t::binary:
14288 case value_t::discarded:
14289 default: {
14290 JSON_THROW(type_error::create(
14291 317,
14292 concat("to serialize to BSON, top-level type must be object, but is ",
14293 j.type_name()),
14294 &j));
14295 }
14296 }
14297 }
14298
14302 void write_cbor(const BasicJsonType& j) {
14303 switch (j.type()) {
14304 case value_t::null: {
14305 oa->write_character(to_char_type(0xF6));
14306 break;
14307 }
14308
14309 case value_t::boolean: {
14310 oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xF5)
14311 : to_char_type(0xF4));
14312 break;
14313 }
14314
14316 if (j.m_data.m_value.number_integer >= 0) {
14317 // CBOR does not differentiate between positive signed
14318 // integers and unsigned integers. Therefore, we used the
14319 // code from the value_t::number_unsigned case here.
14320 if (j.m_data.m_value.number_integer <= 0x17) {
14321 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14322 } else if (j.m_data.m_value.number_integer <=
14323 (std::numeric_limits<std::uint8_t>::max)()) {
14324 oa->write_character(to_char_type(0x18));
14325 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14326 } else if (j.m_data.m_value.number_integer <=
14327 (std::numeric_limits<std::uint16_t>::max)()) {
14328 oa->write_character(to_char_type(0x19));
14329 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
14330 } else if (j.m_data.m_value.number_integer <=
14331 (std::numeric_limits<std::uint32_t>::max)()) {
14332 oa->write_character(to_char_type(0x1A));
14333 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
14334 } else {
14335 oa->write_character(to_char_type(0x1B));
14336 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
14337 }
14338 } else {
14339 // The conversions below encode the sign in the first
14340 // byte, and the value is converted to a positive number.
14341 const auto positive_number = -1 - j.m_data.m_value.number_integer;
14342 if (j.m_data.m_value.number_integer >= -24) {
14343 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
14344 } else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) {
14345 oa->write_character(to_char_type(0x38));
14346 write_number(static_cast<std::uint8_t>(positive_number));
14347 } else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) {
14348 oa->write_character(to_char_type(0x39));
14349 write_number(static_cast<std::uint16_t>(positive_number));
14350 } else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) {
14351 oa->write_character(to_char_type(0x3A));
14352 write_number(static_cast<std::uint32_t>(positive_number));
14353 } else {
14354 oa->write_character(to_char_type(0x3B));
14355 write_number(static_cast<std::uint64_t>(positive_number));
14356 }
14357 }
14358 break;
14359 }
14360
14362 if (j.m_data.m_value.number_unsigned <= 0x17) {
14363 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
14364 } else if (j.m_data.m_value.number_unsigned <=
14365 (std::numeric_limits<std::uint8_t>::max)()) {
14366 oa->write_character(to_char_type(0x18));
14367 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
14368 } else if (j.m_data.m_value.number_unsigned <=
14369 (std::numeric_limits<std::uint16_t>::max)()) {
14370 oa->write_character(to_char_type(0x19));
14371 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
14372 } else if (j.m_data.m_value.number_unsigned <=
14373 (std::numeric_limits<std::uint32_t>::max)()) {
14374 oa->write_character(to_char_type(0x1A));
14375 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
14376 } else {
14377 oa->write_character(to_char_type(0x1B));
14378 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
14379 }
14380 break;
14381 }
14382
14383 case value_t::number_float: {
14384 if (std::isnan(j.m_data.m_value.number_float)) {
14385 // NaN is 0xf97e00 in CBOR
14386 oa->write_character(to_char_type(0xF9));
14387 oa->write_character(to_char_type(0x7E));
14388 oa->write_character(to_char_type(0x00));
14389 } else if (std::isinf(j.m_data.m_value.number_float)) {
14390 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
14391 oa->write_character(to_char_type(0xf9));
14392 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C)
14393 : to_char_type(0xFC));
14394 oa->write_character(to_char_type(0x00));
14395 } else {
14396 write_compact_float(j.m_data.m_value.number_float,
14397 detail::input_format_t::cbor);
14398 }
14399 break;
14400 }
14401
14402 case value_t::string: {
14403 // step 1: write control byte and the string length
14404 const auto N = j.m_data.m_value.string->size();
14405 if (N <= 0x17) {
14406 write_number(static_cast<std::uint8_t>(0x60 + N));
14407 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14408 oa->write_character(to_char_type(0x78));
14409 write_number(static_cast<std::uint8_t>(N));
14410 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14411 oa->write_character(to_char_type(0x79));
14412 write_number(static_cast<std::uint16_t>(N));
14413 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14414 oa->write_character(to_char_type(0x7A));
14415 write_number(static_cast<std::uint32_t>(N));
14416 }
14417 // LCOV_EXCL_START
14418 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
14419 oa->write_character(to_char_type(0x7B));
14420 write_number(static_cast<std::uint64_t>(N));
14421 }
14422 // LCOV_EXCL_STOP
14423
14424 // step 2: write the string
14425 oa->write_characters(
14426 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
14427 j.m_data.m_value.string->size());
14428 break;
14429 }
14430
14431 case value_t::array: {
14432 // step 1: write control byte and the array size
14433 const auto N = j.m_data.m_value.array->size();
14434 if (N <= 0x17) {
14435 write_number(static_cast<std::uint8_t>(0x80 + N));
14436 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14437 oa->write_character(to_char_type(0x98));
14438 write_number(static_cast<std::uint8_t>(N));
14439 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14440 oa->write_character(to_char_type(0x99));
14441 write_number(static_cast<std::uint16_t>(N));
14442 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14443 oa->write_character(to_char_type(0x9A));
14444 write_number(static_cast<std::uint32_t>(N));
14445 }
14446 // LCOV_EXCL_START
14447 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
14448 oa->write_character(to_char_type(0x9B));
14449 write_number(static_cast<std::uint64_t>(N));
14450 }
14451 // LCOV_EXCL_STOP
14452
14453 // step 2: write each element
14454 for (const auto& el : *j.m_data.m_value.array) {
14455 write_cbor(el);
14456 }
14457 break;
14458 }
14459
14460 case value_t::binary: {
14461 if (j.m_data.m_value.binary->has_subtype()) {
14462 if (j.m_data.m_value.binary->subtype() <=
14463 (std::numeric_limits<std::uint8_t>::max)()) {
14464 write_number(static_cast<std::uint8_t>(0xd8));
14465 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
14466 } else if (j.m_data.m_value.binary->subtype() <=
14467 (std::numeric_limits<std::uint16_t>::max)()) {
14468 write_number(static_cast<std::uint8_t>(0xd9));
14469 write_number(
14470 static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
14471 } else if (j.m_data.m_value.binary->subtype() <=
14472 (std::numeric_limits<std::uint32_t>::max)()) {
14473 write_number(static_cast<std::uint8_t>(0xda));
14474 write_number(
14475 static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
14476 } else if (j.m_data.m_value.binary->subtype() <=
14477 (std::numeric_limits<std::uint64_t>::max)()) {
14478 write_number(static_cast<std::uint8_t>(0xdb));
14479 write_number(
14480 static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
14481 }
14482 }
14483
14484 // step 1: write control byte and the binary array size
14485 const auto N = j.m_data.m_value.binary->size();
14486 if (N <= 0x17) {
14487 write_number(static_cast<std::uint8_t>(0x40 + N));
14488 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14489 oa->write_character(to_char_type(0x58));
14490 write_number(static_cast<std::uint8_t>(N));
14491 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14492 oa->write_character(to_char_type(0x59));
14493 write_number(static_cast<std::uint16_t>(N));
14494 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14495 oa->write_character(to_char_type(0x5A));
14496 write_number(static_cast<std::uint32_t>(N));
14497 }
14498 // LCOV_EXCL_START
14499 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
14500 oa->write_character(to_char_type(0x5B));
14501 write_number(static_cast<std::uint64_t>(N));
14502 }
14503 // LCOV_EXCL_STOP
14504
14505 // step 2: write each element
14506 oa->write_characters(
14507 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
14508
14509 break;
14510 }
14511
14512 case value_t::object: {
14513 // step 1: write control byte and the object size
14514 const auto N = j.m_data.m_value.object->size();
14515 if (N <= 0x17) {
14516 write_number(static_cast<std::uint8_t>(0xA0 + N));
14517 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14518 oa->write_character(to_char_type(0xB8));
14519 write_number(static_cast<std::uint8_t>(N));
14520 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14521 oa->write_character(to_char_type(0xB9));
14522 write_number(static_cast<std::uint16_t>(N));
14523 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14524 oa->write_character(to_char_type(0xBA));
14525 write_number(static_cast<std::uint32_t>(N));
14526 }
14527 // LCOV_EXCL_START
14528 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) {
14529 oa->write_character(to_char_type(0xBB));
14530 write_number(static_cast<std::uint64_t>(N));
14531 }
14532 // LCOV_EXCL_STOP
14533
14534 // step 2: write each element
14535 for (const auto& el : *j.m_data.m_value.object) {
14536 write_cbor(el.first);
14537 write_cbor(el.second);
14538 }
14539 break;
14540 }
14541
14542 case value_t::discarded:
14543 default:
14544 break;
14545 }
14546 }
14547
14551 void write_msgpack(const BasicJsonType& j) {
14552 switch (j.type()) {
14553 case value_t::null: // nil
14554 {
14555 oa->write_character(to_char_type(0xC0));
14556 break;
14557 }
14558
14559 case value_t::boolean: // true and false
14560 {
14561 oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xC3)
14562 : to_char_type(0xC2));
14563 break;
14564 }
14565
14567 if (j.m_data.m_value.number_integer >= 0) {
14568 // MessagePack does not differentiate between positive
14569 // signed integers and unsigned integers. Therefore, we used
14570 // the code from the value_t::number_unsigned case here.
14571 if (j.m_data.m_value.number_unsigned < 128) {
14572 // positive fixnum
14573 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14574 } else if (j.m_data.m_value.number_unsigned <=
14575 (std::numeric_limits<std::uint8_t>::max)()) {
14576 // uint 8
14577 oa->write_character(to_char_type(0xCC));
14578 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14579 } else if (j.m_data.m_value.number_unsigned <=
14580 (std::numeric_limits<std::uint16_t>::max)()) {
14581 // uint 16
14582 oa->write_character(to_char_type(0xCD));
14583 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
14584 } else if (j.m_data.m_value.number_unsigned <=
14585 (std::numeric_limits<std::uint32_t>::max)()) {
14586 // uint 32
14587 oa->write_character(to_char_type(0xCE));
14588 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
14589 } else if (j.m_data.m_value.number_unsigned <=
14590 (std::numeric_limits<std::uint64_t>::max)()) {
14591 // uint 64
14592 oa->write_character(to_char_type(0xCF));
14593 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
14594 }
14595 } else {
14596 if (j.m_data.m_value.number_integer >= -32) {
14597 // negative fixnum
14598 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
14599 } else if (j.m_data.m_value.number_integer >=
14600 (std::numeric_limits<std::int8_t>::min)() &&
14601 j.m_data.m_value.number_integer <=
14602 (std::numeric_limits<std::int8_t>::max)()) {
14603 // int 8
14604 oa->write_character(to_char_type(0xD0));
14605 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
14606 } else if (j.m_data.m_value.number_integer >=
14607 (std::numeric_limits<std::int16_t>::min)() &&
14608 j.m_data.m_value.number_integer <=
14609 (std::numeric_limits<std::int16_t>::max)()) {
14610 // int 16
14611 oa->write_character(to_char_type(0xD1));
14612 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
14613 } else if (j.m_data.m_value.number_integer >=
14614 (std::numeric_limits<std::int32_t>::min)() &&
14615 j.m_data.m_value.number_integer <=
14616 (std::numeric_limits<std::int32_t>::max)()) {
14617 // int 32
14618 oa->write_character(to_char_type(0xD2));
14619 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
14620 } else if (j.m_data.m_value.number_integer >=
14621 (std::numeric_limits<std::int64_t>::min)() &&
14622 j.m_data.m_value.number_integer <=
14623 (std::numeric_limits<std::int64_t>::max)()) {
14624 // int 64
14625 oa->write_character(to_char_type(0xD3));
14626 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
14627 }
14628 }
14629 break;
14630 }
14631
14633 if (j.m_data.m_value.number_unsigned < 128) {
14634 // positive fixnum
14635 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14636 } else if (j.m_data.m_value.number_unsigned <=
14637 (std::numeric_limits<std::uint8_t>::max)()) {
14638 // uint 8
14639 oa->write_character(to_char_type(0xCC));
14640 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
14641 } else if (j.m_data.m_value.number_unsigned <=
14642 (std::numeric_limits<std::uint16_t>::max)()) {
14643 // uint 16
14644 oa->write_character(to_char_type(0xCD));
14645 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
14646 } else if (j.m_data.m_value.number_unsigned <=
14647 (std::numeric_limits<std::uint32_t>::max)()) {
14648 // uint 32
14649 oa->write_character(to_char_type(0xCE));
14650 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
14651 } else if (j.m_data.m_value.number_unsigned <=
14652 (std::numeric_limits<std::uint64_t>::max)()) {
14653 // uint 64
14654 oa->write_character(to_char_type(0xCF));
14655 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
14656 }
14657 break;
14658 }
14659
14660 case value_t::number_float: {
14661 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
14662 break;
14663 }
14664
14665 case value_t::string: {
14666 // step 1: write control byte and the string length
14667 const auto N = j.m_data.m_value.string->size();
14668 if (N <= 31) {
14669 // fixstr
14670 write_number(static_cast<std::uint8_t>(0xA0 | N));
14671 } else if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14672 // str 8
14673 oa->write_character(to_char_type(0xD9));
14674 write_number(static_cast<std::uint8_t>(N));
14675 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14676 // str 16
14677 oa->write_character(to_char_type(0xDA));
14678 write_number(static_cast<std::uint16_t>(N));
14679 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14680 // str 32
14681 oa->write_character(to_char_type(0xDB));
14682 write_number(static_cast<std::uint32_t>(N));
14683 }
14684
14685 // step 2: write the string
14686 oa->write_characters(
14687 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
14688 j.m_data.m_value.string->size());
14689 break;
14690 }
14691
14692 case value_t::array: {
14693 // step 1: write control byte and the array size
14694 const auto N = j.m_data.m_value.array->size();
14695 if (N <= 15) {
14696 // fixarray
14697 write_number(static_cast<std::uint8_t>(0x90 | N));
14698 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14699 // array 16
14700 oa->write_character(to_char_type(0xDC));
14701 write_number(static_cast<std::uint16_t>(N));
14702 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14703 // array 32
14704 oa->write_character(to_char_type(0xDD));
14705 write_number(static_cast<std::uint32_t>(N));
14706 }
14707
14708 // step 2: write each element
14709 for (const auto& el : *j.m_data.m_value.array) {
14710 write_msgpack(el);
14711 }
14712 break;
14713 }
14714
14715 case value_t::binary: {
14716 // step 0: determine if the binary type has a set subtype to
14717 // determine whether or not to use the ext or fixext types
14718 const bool use_ext = j.m_data.m_value.binary->has_subtype();
14719
14720 // step 1: write control byte and the byte string length
14721 const auto N = j.m_data.m_value.binary->size();
14722 if (N <= (std::numeric_limits<std::uint8_t>::max)()) {
14723 std::uint8_t output_type{};
14724 bool fixed = true;
14725 if (use_ext) {
14726 switch (N) {
14727 case 1:
14728 output_type = 0xD4; // fixext 1
14729 break;
14730 case 2:
14731 output_type = 0xD5; // fixext 2
14732 break;
14733 case 4:
14734 output_type = 0xD6; // fixext 4
14735 break;
14736 case 8:
14737 output_type = 0xD7; // fixext 8
14738 break;
14739 case 16:
14740 output_type = 0xD8; // fixext 16
14741 break;
14742 default:
14743 output_type = 0xC7; // ext 8
14744 fixed = false;
14745 break;
14746 }
14747
14748 } else {
14749 output_type = 0xC4; // bin 8
14750 fixed = false;
14751 }
14752
14753 oa->write_character(to_char_type(output_type));
14754 if (!fixed) {
14755 write_number(static_cast<std::uint8_t>(N));
14756 }
14757 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14758 const std::uint8_t output_type = use_ext ? 0xC8 // ext 16
14759 : 0xC5; // bin 16
14760
14761 oa->write_character(to_char_type(output_type));
14762 write_number(static_cast<std::uint16_t>(N));
14763 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14764 const std::uint8_t output_type = use_ext ? 0xC9 // ext 32
14765 : 0xC6; // bin 32
14766
14767 oa->write_character(to_char_type(output_type));
14768 write_number(static_cast<std::uint32_t>(N));
14769 }
14770
14771 // step 1.5: if this is an ext type, write the subtype
14772 if (use_ext) {
14773 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
14774 }
14775
14776 // step 2: write the byte string
14777 oa->write_characters(
14778 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
14779
14780 break;
14781 }
14782
14783 case value_t::object: {
14784 // step 1: write control byte and the object size
14785 const auto N = j.m_data.m_value.object->size();
14786 if (N <= 15) {
14787 // fixmap
14788 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
14789 } else if (N <= (std::numeric_limits<std::uint16_t>::max)()) {
14790 // map 16
14791 oa->write_character(to_char_type(0xDE));
14792 write_number(static_cast<std::uint16_t>(N));
14793 } else if (N <= (std::numeric_limits<std::uint32_t>::max)()) {
14794 // map 32
14795 oa->write_character(to_char_type(0xDF));
14796 write_number(static_cast<std::uint32_t>(N));
14797 }
14798
14799 // step 2: write each element
14800 for (const auto& el : *j.m_data.m_value.object) {
14801 write_msgpack(el.first);
14802 write_msgpack(el.second);
14803 }
14804 break;
14805 }
14806
14807 case value_t::discarded:
14808 default:
14809 break;
14810 }
14811 }
14812
14820 void write_ubjson(const BasicJsonType& j, const bool use_count, const bool use_type,
14821 const bool add_prefix = true, const bool use_bjdata = false) {
14822 switch (j.type()) {
14823 case value_t::null: {
14824 if (add_prefix) {
14825 oa->write_character(to_char_type('Z'));
14826 }
14827 break;
14828 }
14829
14830 case value_t::boolean: {
14831 if (add_prefix) {
14832 oa->write_character(j.m_data.m_value.boolean ? to_char_type('T')
14833 : to_char_type('F'));
14834 }
14835 break;
14836 }
14837
14839 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix,
14840 use_bjdata);
14841 break;
14842 }
14843
14845 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix,
14846 use_bjdata);
14847 break;
14848 }
14849
14850 case value_t::number_float: {
14851 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix,
14852 use_bjdata);
14853 break;
14854 }
14855
14856 case value_t::string: {
14857 if (add_prefix) {
14858 oa->write_character(to_char_type('S'));
14859 }
14860 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
14861 oa->write_characters(
14862 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
14863 j.m_data.m_value.string->size());
14864 break;
14865 }
14866
14867 case value_t::array: {
14868 if (add_prefix) {
14869 oa->write_character(to_char_type('['));
14870 }
14871
14872 bool prefix_required = true;
14873 if (use_type && !j.m_data.m_value.array->empty()) {
14874 JSON_ASSERT(use_count);
14875 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
14876 const bool same_prefix =
14877 std::all_of(j.begin() + 1, j.end(),
14878 [this, first_prefix, use_bjdata](const BasicJsonType& v) {
14879 return ubjson_prefix(v, use_bjdata) == first_prefix;
14880 });
14881
14882 std::vector<CharType> bjdx = {
14883 '[', '{', 'S', 'H',
14884 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
14885
14886 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(),
14887 first_prefix) != bjdx.end())) {
14888 prefix_required = false;
14889 oa->write_character(to_char_type('$'));
14890 oa->write_character(first_prefix);
14891 }
14892 }
14893
14894 if (use_count) {
14895 oa->write_character(to_char_type('#'));
14896 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true,
14897 use_bjdata);
14898 }
14899
14900 for (const auto& el : *j.m_data.m_value.array) {
14901 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
14902 }
14903
14904 if (!use_count) {
14905 oa->write_character(to_char_type(']'));
14906 }
14907
14908 break;
14909 }
14910
14911 case value_t::binary: {
14912 if (add_prefix) {
14913 oa->write_character(to_char_type('['));
14914 }
14915
14916 if (use_type && !j.m_data.m_value.binary->empty()) {
14917 JSON_ASSERT(use_count);
14918 oa->write_character(to_char_type('$'));
14919 oa->write_character('U');
14920 }
14921
14922 if (use_count) {
14923 oa->write_character(to_char_type('#'));
14924 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true,
14925 use_bjdata);
14926 }
14927
14928 if (use_type) {
14929 oa->write_characters(
14930 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
14931 j.m_data.m_value.binary->size());
14932 } else {
14933 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) {
14934 oa->write_character(to_char_type('U'));
14935 oa->write_character(j.m_data.m_value.binary->data()[i]);
14936 }
14937 }
14938
14939 if (!use_count) {
14940 oa->write_character(to_char_type(']'));
14941 }
14942
14943 break;
14944 }
14945
14946 case value_t::object: {
14947 if (use_bjdata && j.m_data.m_value.object->size() == 3 &&
14948 j.m_data.m_value.object->find("_ArrayType_") !=
14949 j.m_data.m_value.object->end() &&
14950 j.m_data.m_value.object->find("_ArraySize_") !=
14951 j.m_data.m_value.object->end() &&
14952 j.m_data.m_value.object->find("_ArrayData_") !=
14953 j.m_data.m_value.object->end()) {
14954 if (!write_bjdata_ndarray(
14955 *j.m_data.m_value.object, use_count,
14956 use_type)) // decode bjdata ndarray in the JData format
14957 // (https://github.com/NeuroJSON/jdata)
14958 {
14959 break;
14960 }
14961 }
14962
14963 if (add_prefix) {
14964 oa->write_character(to_char_type('{'));
14965 }
14966
14967 bool prefix_required = true;
14968 if (use_type && !j.m_data.m_value.object->empty()) {
14969 JSON_ASSERT(use_count);
14970 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
14971 const bool same_prefix =
14972 std::all_of(j.begin(), j.end(),
14973 [this, first_prefix, use_bjdata](const BasicJsonType& v) {
14974 return ubjson_prefix(v, use_bjdata) == first_prefix;
14975 });
14976
14977 std::vector<CharType> bjdx = {
14978 '[', '{', 'S', 'H',
14979 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
14980
14981 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(),
14982 first_prefix) != bjdx.end())) {
14983 prefix_required = false;
14984 oa->write_character(to_char_type('$'));
14985 oa->write_character(first_prefix);
14986 }
14987 }
14988
14989 if (use_count) {
14990 oa->write_character(to_char_type('#'));
14991 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true,
14992 use_bjdata);
14993 }
14994
14995 for (const auto& el : *j.m_data.m_value.object) {
14996 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
14997 oa->write_characters(reinterpret_cast<const CharType*>(el.first.c_str()),
14998 el.first.size());
14999 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15000 }
15001
15002 if (!use_count) {
15003 oa->write_character(to_char_type('}'));
15004 }
15005
15006 break;
15007 }
15008
15009 case value_t::discarded:
15010 default:
15011 break;
15012 }
15013 }
15014
15015 private:
15017 // BSON //
15019
15024 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) {
15025 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15026 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) {
15027 JSON_THROW(
15028 out_of_range::create(409,
15029 concat("BSON key cannot contain code point U+0000 (at byte ",
15030 std::to_string(it), ")"),
15031 &j));
15032 static_cast<void>(j);
15033 }
15034
15035 return /*id*/ 1ul + name.size() + /*zero-terminator*/ 1u;
15036 }
15037
15041 void write_bson_entry_header(const string_t& name, const std::uint8_t element_type) {
15042 oa->write_character(to_char_type(element_type)); // boolean
15043 oa->write_characters(reinterpret_cast<const CharType*>(name.c_str()), name.size() + 1u);
15044 }
15045
15049 void write_bson_boolean(const string_t& name, const bool value) {
15050 write_bson_entry_header(name, 0x08);
15051 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15052 }
15053
15057 void write_bson_double(const string_t& name, const double value) {
15058 write_bson_entry_header(name, 0x01);
15059 write_number<double>(value, true);
15060 }
15061
15065 static std::size_t calc_bson_string_size(const string_t& value) {
15066 return sizeof(std::int32_t) + value.size() + 1ul;
15067 }
15068
15072 void write_bson_string(const string_t& name, const string_t& value) {
15073 write_bson_entry_header(name, 0x02);
15074
15075 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15076 oa->write_characters(reinterpret_cast<const CharType*>(value.c_str()), value.size() + 1);
15077 }
15078
15082 void write_bson_null(const string_t& name) { write_bson_entry_header(name, 0x0A); }
15083
15087 static std::size_t calc_bson_integer_size(const std::int64_t value) {
15088 return (std::numeric_limits<std::int32_t>::min)() <= value &&
15089 value <= (std::numeric_limits<std::int32_t>::max)()
15090 ? sizeof(std::int32_t)
15091 : sizeof(std::int64_t);
15092 }
15093
15097 void write_bson_integer(const string_t& name, const std::int64_t value) {
15098 if ((std::numeric_limits<std::int32_t>::min)() <= value &&
15099 value <= (std::numeric_limits<std::int32_t>::max)()) {
15100 write_bson_entry_header(name, 0x10); // int32
15101 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
15102 } else {
15103 write_bson_entry_header(name, 0x12); // int64
15104 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
15105 }
15106 }
15107
15111 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept {
15112 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
15113 ? sizeof(std::int32_t)
15114 : sizeof(std::int64_t);
15115 }
15116
15120 void write_bson_unsigned(const string_t& name, const BasicJsonType& j) {
15121 if (j.m_data.m_value.number_unsigned <=
15122 static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
15123 write_bson_entry_header(name, 0x10 /* int32 */);
15124 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned),
15125 true);
15126 } else if (j.m_data.m_value.number_unsigned <=
15127 static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
15128 write_bson_entry_header(name, 0x12 /* int64 */);
15129 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned),
15130 true);
15131 } else {
15132 JSON_THROW(out_of_range::create(
15133 407,
15134 concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned),
15135 " cannot be represented by BSON as it does not fit int64"),
15136 &j));
15137 }
15138 }
15139
15143 void write_bson_object_entry(const string_t& name,
15144 const typename BasicJsonType::object_t& value) {
15145 write_bson_entry_header(name, 0x03); // object
15146 write_bson_object(value);
15147 }
15148
15152 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) {
15153 std::size_t array_index = 0ul;
15154
15155 const std::size_t embedded_document_size = std::accumulate(
15156 std::begin(value), std::end(value), static_cast<std::size_t>(0),
15157 [&array_index](std::size_t result,
15158 const typename BasicJsonType::array_t::value_type& el) {
15159 return result + calc_bson_element_size(std::to_string(array_index++), el);
15160 });
15161
15162 return sizeof(std::int32_t) + embedded_document_size + 1ul;
15163 }
15164
15168 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) {
15169 return sizeof(std::int32_t) + value.size() + 1ul;
15170 }
15171
15175 void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value) {
15176 write_bson_entry_header(name, 0x04); // array
15177 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
15178
15179 std::size_t array_index = 0ul;
15180
15181 for (const auto& el : value) {
15182 write_bson_element(std::to_string(array_index++), el);
15183 }
15184
15185 oa->write_character(to_char_type(0x00));
15186 }
15187
15191 void write_bson_binary(const string_t& name, const binary_t& value) {
15192 write_bson_entry_header(name, 0x05);
15193
15194 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
15195 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype())
15196 : static_cast<std::uint8_t>(0x00));
15197
15198 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
15199 }
15200
15207 static std::size_t calc_bson_element_size(const string_t& name, const BasicJsonType& j) {
15208 const auto header_size = calc_bson_entry_header_size(name, j);
15209 switch (j.type()) {
15210 case value_t::object:
15211 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
15212
15213 case value_t::array:
15214 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
15215
15216 case value_t::binary:
15217 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
15218
15219 case value_t::boolean:
15220 return header_size + 1ul;
15221
15222 case value_t::number_float:
15223 return header_size + 8ul;
15224
15225 case value_t::number_integer:
15226 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
15227
15228 case value_t::number_unsigned:
15229 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
15230
15231 case value_t::string:
15232 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
15233
15234 case value_t::null:
15235 return header_size + 0ul;
15236
15237 // LCOV_EXCL_START
15238 case value_t::discarded:
15239 default:
15240 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15241 return 0ul;
15242 // LCOV_EXCL_STOP
15243 }
15244 }
15245
15252 void write_bson_element(const string_t& name, const BasicJsonType& j) {
15253 switch (j.type()) {
15254 case value_t::object:
15255 return write_bson_object_entry(name, *j.m_data.m_value.object);
15256
15257 case value_t::array:
15258 return write_bson_array(name, *j.m_data.m_value.array);
15259
15260 case value_t::binary:
15261 return write_bson_binary(name, *j.m_data.m_value.binary);
15262
15263 case value_t::boolean:
15264 return write_bson_boolean(name, j.m_data.m_value.boolean);
15265
15266 case value_t::number_float:
15267 return write_bson_double(name, j.m_data.m_value.number_float);
15268
15269 case value_t::number_integer:
15270 return write_bson_integer(name, j.m_data.m_value.number_integer);
15271
15272 case value_t::number_unsigned:
15273 return write_bson_unsigned(name, j);
15274
15275 case value_t::string:
15276 return write_bson_string(name, *j.m_data.m_value.string);
15277
15278 case value_t::null:
15279 return write_bson_null(name);
15280
15281 // LCOV_EXCL_START
15282 case value_t::discarded:
15283 default:
15284 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
15285 return;
15286 // LCOV_EXCL_STOP
15287 }
15288 }
15289
15296 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) {
15297 const std::size_t document_size = std::accumulate(
15298 value.begin(), value.end(), static_cast<std::size_t>(0),
15299 [](size_t result, const typename BasicJsonType::object_t::value_type& el) {
15300 return result += calc_bson_element_size(el.first, el.second);
15301 });
15302
15303 return sizeof(std::int32_t) + document_size + 1ul;
15304 }
15305
15310 void write_bson_object(const typename BasicJsonType::object_t& value) {
15311 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
15312
15313 for (const auto& el : value) {
15314 write_bson_element(el.first, el.second);
15315 }
15316
15317 oa->write_character(to_char_type(0x00));
15318 }
15319
15321 // CBOR //
15323
15324 static constexpr CharType get_cbor_float_prefix(float /*unused*/) {
15325 return to_char_type(0xFA); // Single-Precision Float
15326 }
15327
15328 static constexpr CharType get_cbor_float_prefix(double /*unused*/) {
15329 return to_char_type(0xFB); // Double-Precision Float
15330 }
15331
15333 // MsgPack //
15335
15336 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) {
15337 return to_char_type(0xCA); // float 32
15338 }
15339
15340 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) {
15341 return to_char_type(0xCB); // float 64
15342 }
15343
15345 // UBJSON //
15347
15348 // UBJSON: write number (floating point)
15349 template <typename NumberType,
15350 typename std::enable_if<std::is_floating_point<NumberType>::value, int>::type = 0>
15351 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix,
15352 const bool use_bjdata) {
15353 if (add_prefix) {
15354 oa->write_character(get_ubjson_float_prefix(n));
15355 }
15356 write_number(n, use_bjdata);
15357 }
15358
15359 // UBJSON: write number (unsigned integer)
15360 template <typename NumberType,
15361 typename std::enable_if<std::is_unsigned<NumberType>::value, int>::type = 0>
15362 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix,
15363 const bool use_bjdata) {
15364 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) {
15365 if (add_prefix) {
15366 oa->write_character(to_char_type('i')); // int8
15367 }
15368 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15369 } else if (n <= (std::numeric_limits<std::uint8_t>::max)()) {
15370 if (add_prefix) {
15371 oa->write_character(to_char_type('U')); // uint8
15372 }
15373 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15374 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) {
15375 if (add_prefix) {
15376 oa->write_character(to_char_type('I')); // int16
15377 }
15378 write_number(static_cast<std::int16_t>(n), use_bjdata);
15379 } else if (use_bjdata &&
15380 n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) {
15381 if (add_prefix) {
15382 oa->write_character(to_char_type('u')); // uint16 - bjdata only
15383 }
15384 write_number(static_cast<std::uint16_t>(n), use_bjdata);
15385 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
15386 if (add_prefix) {
15387 oa->write_character(to_char_type('l')); // int32
15388 }
15389 write_number(static_cast<std::int32_t>(n), use_bjdata);
15390 } else if (use_bjdata &&
15391 n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) {
15392 if (add_prefix) {
15393 oa->write_character(to_char_type('m')); // uint32 - bjdata only
15394 }
15395 write_number(static_cast<std::uint32_t>(n), use_bjdata);
15396 } else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
15397 if (add_prefix) {
15398 oa->write_character(to_char_type('L')); // int64
15399 }
15400 write_number(static_cast<std::int64_t>(n), use_bjdata);
15401 } else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) {
15402 if (add_prefix) {
15403 oa->write_character(to_char_type('M')); // uint64 - bjdata only
15404 }
15405 write_number(static_cast<std::uint64_t>(n), use_bjdata);
15406 } else {
15407 if (add_prefix) {
15408 oa->write_character(to_char_type('H')); // high-precision number
15409 }
15410
15411 const auto number = BasicJsonType(n).dump();
15412 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
15413 for (std::size_t i = 0; i < number.size(); ++i) {
15414 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
15415 }
15416 }
15417 }
15418
15419 // UBJSON: write number (signed integer)
15420 template <typename NumberType,
15421 typename std::enable_if<std::is_signed<NumberType>::value &&
15422 !std::is_floating_point<NumberType>::value,
15423 int>::type = 0>
15424 void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix,
15425 const bool use_bjdata) {
15426 if ((std::numeric_limits<std::int8_t>::min)() <= n &&
15427 n <= (std::numeric_limits<std::int8_t>::max)()) {
15428 if (add_prefix) {
15429 oa->write_character(to_char_type('i')); // int8
15430 }
15431 write_number(static_cast<std::int8_t>(n), use_bjdata);
15432 } else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n &&
15433 n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) {
15434 if (add_prefix) {
15435 oa->write_character(to_char_type('U')); // uint8
15436 }
15437 write_number(static_cast<std::uint8_t>(n), use_bjdata);
15438 } else if ((std::numeric_limits<std::int16_t>::min)() <= n &&
15439 n <= (std::numeric_limits<std::int16_t>::max)()) {
15440 if (add_prefix) {
15441 oa->write_character(to_char_type('I')); // int16
15442 }
15443 write_number(static_cast<std::int16_t>(n), use_bjdata);
15444 } else if (use_bjdata &&
15445 (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n &&
15446 n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)()))) {
15447 if (add_prefix) {
15448 oa->write_character(to_char_type('u')); // uint16 - bjdata only
15449 }
15450 write_number(static_cast<uint16_t>(n), use_bjdata);
15451 } else if ((std::numeric_limits<std::int32_t>::min)() <= n &&
15452 n <= (std::numeric_limits<std::int32_t>::max)()) {
15453 if (add_prefix) {
15454 oa->write_character(to_char_type('l')); // int32
15455 }
15456 write_number(static_cast<std::int32_t>(n), use_bjdata);
15457 } else if (use_bjdata &&
15458 (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n &&
15459 n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)()))) {
15460 if (add_prefix) {
15461 oa->write_character(to_char_type('m')); // uint32 - bjdata only
15462 }
15463 write_number(static_cast<uint32_t>(n), use_bjdata);
15464 } else if ((std::numeric_limits<std::int64_t>::min)() <= n &&
15465 n <= (std::numeric_limits<std::int64_t>::max)()) {
15466 if (add_prefix) {
15467 oa->write_character(to_char_type('L')); // int64
15468 }
15469 write_number(static_cast<std::int64_t>(n), use_bjdata);
15470 }
15471 // LCOV_EXCL_START
15472 else {
15473 if (add_prefix) {
15474 oa->write_character(to_char_type('H')); // high-precision number
15475 }
15476
15477 const auto number = BasicJsonType(n).dump();
15478 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
15479 for (std::size_t i = 0; i < number.size(); ++i) {
15480 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
15481 }
15482 }
15483 // LCOV_EXCL_STOP
15484 }
15485
15489 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept {
15490 switch (j.type()) {
15491 case value_t::null:
15492 return 'Z';
15493
15494 case value_t::boolean:
15495 return j.m_data.m_value.boolean ? 'T' : 'F';
15496
15497 case value_t::number_integer: {
15498 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer &&
15499 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) {
15500 return 'i';
15501 }
15502 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer &&
15503 j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) {
15504 return 'U';
15505 }
15506 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer &&
15507 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) {
15508 return 'I';
15509 }
15510 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <=
15511 j.m_data.m_value.number_integer &&
15512 j.m_data.m_value.number_integer <=
15513 (std::numeric_limits<std::uint16_t>::max)())) {
15514 return 'u';
15515 }
15516 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer &&
15517 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) {
15518 return 'l';
15519 }
15520 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <=
15521 j.m_data.m_value.number_integer &&
15522 j.m_data.m_value.number_integer <=
15523 (std::numeric_limits<std::uint32_t>::max)())) {
15524 return 'm';
15525 }
15526 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer &&
15527 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) {
15528 return 'L';
15529 }
15530 // anything else is treated as high-precision number
15531 return 'H'; // LCOV_EXCL_LINE
15532 }
15533
15534 case value_t::number_unsigned: {
15535 if (j.m_data.m_value.number_unsigned <=
15536 static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) {
15537 return 'i';
15538 }
15539 if (j.m_data.m_value.number_unsigned <=
15540 static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) {
15541 return 'U';
15542 }
15543 if (j.m_data.m_value.number_unsigned <=
15544 static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) {
15545 return 'I';
15546 }
15547 if (use_bjdata &&
15548 j.m_data.m_value.number_unsigned <=
15549 static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) {
15550 return 'u';
15551 }
15552 if (j.m_data.m_value.number_unsigned <=
15553 static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) {
15554 return 'l';
15555 }
15556 if (use_bjdata &&
15557 j.m_data.m_value.number_unsigned <=
15558 static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) {
15559 return 'm';
15560 }
15561 if (j.m_data.m_value.number_unsigned <=
15562 static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) {
15563 return 'L';
15564 }
15565 if (use_bjdata && j.m_data.m_value.number_unsigned <=
15566 (std::numeric_limits<std::uint64_t>::max)()) {
15567 return 'M';
15568 }
15569 // anything else is treated as high-precision number
15570 return 'H'; // LCOV_EXCL_LINE
15571 }
15572
15573 case value_t::number_float:
15574 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
15575
15576 case value_t::string:
15577 return 'S';
15578
15579 case value_t::array: // fallthrough
15580 case value_t::binary:
15581 return '[';
15582
15583 case value_t::object:
15584 return '{';
15585
15586 case value_t::discarded:
15587 default: // discarded values
15588 return 'N';
15589 }
15590 }
15591
15592 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) {
15593 return 'd'; // float 32
15594 }
15595
15596 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) {
15597 return 'D'; // float 64
15598 }
15599
15604 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count,
15605 const bool use_type) {
15606 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'},
15607 {"int16", 'I'}, {"uint32", 'm'}, {"int32", 'l'},
15608 {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'},
15609 {"double", 'D'}, {"char", 'C'}};
15610
15611 string_t key = "_ArrayType_";
15612 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
15613 if (it == bjdtype.end()) {
15614 return true;
15615 }
15616 CharType dtype = it->second;
15617
15618 key = "_ArraySize_";
15619 std::size_t len = (value.at(key).empty() ? 0 : 1);
15620 for (const auto& el : value.at(key)) {
15621 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
15622 }
15623
15624 key = "_ArrayData_";
15625 if (value.at(key).size() != len) {
15626 return true;
15627 }
15628
15629 oa->write_character('[');
15630 oa->write_character('$');
15631 oa->write_character(dtype);
15632 oa->write_character('#');
15633
15634 key = "_ArraySize_";
15635 write_ubjson(value.at(key), use_count, use_type, true, true);
15636
15637 key = "_ArrayData_";
15638 if (dtype == 'U' || dtype == 'C') {
15639 for (const auto& el : value.at(key)) {
15640 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
15641 }
15642 } else if (dtype == 'i') {
15643 for (const auto& el : value.at(key)) {
15644 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
15645 }
15646 } else if (dtype == 'u') {
15647 for (const auto& el : value.at(key)) {
15648 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
15649 }
15650 } else if (dtype == 'I') {
15651 for (const auto& el : value.at(key)) {
15652 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
15653 }
15654 } else if (dtype == 'm') {
15655 for (const auto& el : value.at(key)) {
15656 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
15657 }
15658 } else if (dtype == 'l') {
15659 for (const auto& el : value.at(key)) {
15660 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
15661 }
15662 } else if (dtype == 'M') {
15663 for (const auto& el : value.at(key)) {
15664 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
15665 }
15666 } else if (dtype == 'L') {
15667 for (const auto& el : value.at(key)) {
15668 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
15669 }
15670 } else if (dtype == 'd') {
15671 for (const auto& el : value.at(key)) {
15672 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
15673 }
15674 } else if (dtype == 'D') {
15675 for (const auto& el : value.at(key)) {
15676 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
15677 }
15678 }
15679 return false;
15680 }
15681
15683 // Utility functions //
15685
15686 /*
15687 @brief write a number to output input
15688 @param[in] n number of type @a NumberType
15689 @param[in] OutputIsLittleEndian Set to true if output data is
15690 required to be little endian
15691 @tparam NumberType the type of the number
15692
15693 @note This function needs to respect the system's endianness, because bytes
15694 in CBOR, MessagePack, and UBJSON are stored in network order (big
15695 endian) and therefore need reordering on little endian systems.
15696 On the other hand, BSON and BJData use little endian and should reorder
15697 on big endian systems.
15698 */
15699 template <typename NumberType>
15700 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) {
15701 // step 1: write number to array of length NumberType
15702 std::array<CharType, sizeof(NumberType)> vec{};
15703 std::memcpy(vec.data(), &n, sizeof(NumberType));
15704
15705 // step 2: write array to output (with possible reordering)
15706 if (is_little_endian != OutputIsLittleEndian) {
15707 // reverse byte order prior to conversion if necessary
15708 std::reverse(vec.begin(), vec.end());
15709 }
15710
15711 oa->write_characters(vec.data(), sizeof(NumberType));
15712 }
15713
15714 void write_compact_float(const number_float_t n, detail::input_format_t format) {
15715#ifdef __GNUC__
15716#pragma GCC diagnostic push
15717#pragma GCC diagnostic ignored "-Wfloat-equal"
15718#endif
15719 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
15720 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
15721 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)) {
15722 oa->write_character(format == detail::input_format_t::cbor
15723 ? get_cbor_float_prefix(static_cast<float>(n))
15724 : get_msgpack_float_prefix(static_cast<float>(n)));
15725 write_number(static_cast<float>(n));
15726 } else {
15727 oa->write_character(format == detail::input_format_t::cbor
15728 ? get_cbor_float_prefix(n)
15729 : get_msgpack_float_prefix(n));
15730 write_number(n);
15731 }
15732#ifdef __GNUC__
15733#pragma GCC diagnostic pop
15734#endif
15735 }
15736
15737 public:
15738 // The following to_char_type functions are implement the conversion
15739 // between uint8_t and CharType. In case CharType is not unsigned,
15740 // such a conversion is required to allow values greater than 128.
15741 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
15742 template <typename C = CharType,
15743 enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value>* = nullptr>
15744 static constexpr CharType to_char_type(std::uint8_t x) noexcept {
15745 return *reinterpret_cast<char*>(&x);
15746 }
15747
15748 template <typename C = CharType,
15749 enable_if_t<std::is_signed<C>::value && std::is_unsigned<char>::value>* = nullptr>
15750 static CharType to_char_type(std::uint8_t x) noexcept {
15751 static_assert(sizeof(std::uint8_t) == sizeof(CharType),
15752 "size of CharType must be equal to std::uint8_t");
15753 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
15754 CharType result;
15755 std::memcpy(&result, &x, sizeof(x));
15756 return result;
15757 }
15758
15759 template <typename C = CharType, enable_if_t<std::is_unsigned<C>::value>* = nullptr>
15760 static constexpr CharType to_char_type(std::uint8_t x) noexcept {
15761 return x;
15762 }
15763
15764 template <
15765 typename InputCharType, typename C = CharType,
15766 enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value &&
15767 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value>* =
15768 nullptr>
15769 static constexpr CharType to_char_type(InputCharType x) noexcept {
15770 return x;
15771 }
15772
15773 private:
15775 const bool is_little_endian = little_endianness();
15776
15778 output_adapter_t<CharType> oa = nullptr;
15779};
15780
15781} // namespace detail
15782NLOHMANN_JSON_NAMESPACE_END
15783
15784// #include <nlohmann/detail/output/output_adapters.hpp>
15785
15786// #include <nlohmann/detail/output/serializer.hpp>
15787// __ _____ _____ _____
15788// __| | __| | | | JSON for Modern C++
15789// | | |__ | | | | | | version 3.11.3
15790// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15791//
15792// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
15793// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
15794// SPDX-License-Identifier: MIT
15795
15796#include <algorithm> // reverse, remove, fill, find, none_of
15797#include <array> // array
15798#include <clocale> // localeconv, lconv
15799#include <cmath> // labs, isfinite, isnan, signbit
15800#include <cstddef> // size_t, ptrdiff_t
15801#include <cstdint> // uint8_t
15802#include <cstdio> // snprintf
15803#include <iomanip> // setfill, setw
15804#include <limits> // numeric_limits
15805#include <string> // string, char_traits
15806#include <type_traits> // is_same
15807#include <utility> // move
15808
15809// #include <nlohmann/detail/conversions/to_chars.hpp>
15810// __ _____ _____ _____
15811// __| | __| | | | JSON for Modern C++
15812// | | |__ | | | | | | version 3.11.3
15813// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15814//
15815// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
15816// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
15817// SPDX-License-Identifier: MIT
15818
15819#include <array> // array
15820#include <cmath> // signbit, isfinite
15821#include <cstdint> // intN_t, uintN_t
15822#include <cstring> // memcpy, memmove
15823#include <limits> // numeric_limits
15824#include <type_traits> // conditional
15825
15826// #include <nlohmann/detail/macro_scope.hpp>
15827
15828NLOHMANN_JSON_NAMESPACE_BEGIN
15829namespace detail {
15830
15851namespace dtoa_impl {
15852
15853template <typename Target, typename Source> Target reinterpret_bits(const Source source) {
15854 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
15855
15856 Target target;
15857 std::memcpy(&target, &source, sizeof(Source));
15858 return target;
15859}
15860
15861struct diyfp // f * 2^e
15862{
15863 static constexpr int kPrecision = 64; // = q
15864
15865 std::uint64_t f = 0;
15866 int e = 0;
15867
15868 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
15869
15874 static diyfp sub(const diyfp& x, const diyfp& y) noexcept {
15875 JSON_ASSERT(x.e == y.e);
15876 JSON_ASSERT(x.f >= y.f);
15877
15878 return {x.f - y.f, x.e};
15879 }
15880
15885 static diyfp mul(const diyfp& x, const diyfp& y) noexcept {
15886 static_assert(kPrecision == 64, "internal error");
15887
15888 // Computes:
15889 // f = round((x.f * y.f) / 2^q)
15890 // e = x.e + y.e + q
15891
15892 // Emulate the 64-bit * 64-bit multiplication:
15893 //
15894 // p = u * v
15895 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
15896 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) +
15897 // 2^64 (u_hi v_hi ) = (p0 ) + 2^32 ((p1 ) + (p2 ))
15898 // + 2^64 (p3 ) = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo +
15899 // 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) =
15900 // (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi +
15901 // p2_hi + p3) = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) = (p0_lo ) +
15902 // 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
15903 //
15904 // (Since Q might be larger than 2^32 - 1)
15905 //
15906 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
15907 //
15908 // (Q_hi + H does not overflow a 64-bit int)
15909 //
15910 // = p_lo + 2^64 p_hi
15911
15912 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
15913 const std::uint64_t u_hi = x.f >> 32u;
15914 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
15915 const std::uint64_t v_hi = y.f >> 32u;
15916
15917 const std::uint64_t p0 = u_lo * v_lo;
15918 const std::uint64_t p1 = u_lo * v_hi;
15919 const std::uint64_t p2 = u_hi * v_lo;
15920 const std::uint64_t p3 = u_hi * v_hi;
15921
15922 const std::uint64_t p0_hi = p0 >> 32u;
15923 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
15924 const std::uint64_t p1_hi = p1 >> 32u;
15925 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
15926 const std::uint64_t p2_hi = p2 >> 32u;
15927
15928 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
15929
15930 // The full product might now be computed as
15931 //
15932 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
15933 // p_lo = p0_lo + (Q << 32)
15934 //
15935 // But in this particular case here, the full p_lo is not required.
15936 // Effectively we only need to add the highest bit in p_lo to p_hi (and
15937 // Q_hi + 1 does not overflow).
15938
15939 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
15940
15941 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
15942
15943 return {h, x.e + y.e + 64};
15944 }
15945
15950 static diyfp normalize(diyfp x) noexcept {
15951 JSON_ASSERT(x.f != 0);
15952
15953 while ((x.f >> 63u) == 0) {
15954 x.f <<= 1u;
15955 x.e--;
15956 }
15957
15958 return x;
15959 }
15960
15965 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept {
15966 const int delta = x.e - target_exponent;
15967
15968 JSON_ASSERT(delta >= 0);
15969 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
15970
15971 return {x.f << delta, target_exponent};
15972 }
15973};
15974
15976 diyfp w;
15977 diyfp minus;
15978 diyfp plus;
15979};
15980
15987template <typename FloatType> boundaries compute_boundaries(FloatType value) {
15988 JSON_ASSERT(std::isfinite(value));
15989 JSON_ASSERT(value > 0);
15990
15991 // Convert the IEEE representation into a diyfp.
15992 //
15993 // If v is denormal:
15994 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15995 // If v is normalized:
15996 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15997
15998 static_assert(std::numeric_limits<FloatType>::is_iec559,
15999 "internal error: dtoa_short requires an IEEE-754 "
16000 "floating-point implementation");
16001
16002 constexpr int kPrecision =
16003 std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
16004 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
16005 constexpr int kMinExp = 1 - kBias;
16006 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
16007
16008 using bits_type =
16009 typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t>::type;
16010
16011 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
16012 const std::uint64_t E = bits >> (kPrecision - 1);
16013 const std::uint64_t F = bits & (kHiddenBit - 1);
16014
16015 const bool is_denormal = E == 0;
16016 const diyfp v =
16017 is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
16018
16019 // Compute the boundaries m- and m+ of the floating-point value
16020 // v = f * 2^e.
16021 //
16022 // Determine v- and v+, the floating-point predecessor and successor if v,
16023 // respectively.
16024 //
16025 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
16026 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
16027 //
16028 // v+ = v + 2^e
16029 //
16030 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
16031 // between m- and m+ round to v, regardless of how the input rounding
16032 // algorithm breaks ties.
16033 //
16034 // ---+-------------+-------------+-------------+-------------+--- (A)
16035 // v- m- v m+ v+
16036 //
16037 // -----------------+------+------+-------------+-------------+--- (B)
16038 // v- m- v m+ v+
16039
16040 const bool lower_boundary_is_closer = F == 0 && E > 1;
16041 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
16042 const diyfp m_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B)
16043 : diyfp(2 * v.f - 1, v.e - 1); // (A)
16044
16045 // Determine the normalized w+ = m+.
16046 const diyfp w_plus = diyfp::normalize(m_plus);
16047
16048 // Determine w- = m- such that e_(w-) = e_(w+).
16049 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
16050
16051 return {diyfp::normalize(v), w_minus, w_plus};
16052}
16053
16054// Given normalized diyfp w, Grisu needs to find a (normalized) cached
16055// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
16056// within a certain range [alpha, gamma] (Definition 3.2 from [1])
16057//
16058// alpha <= e = e_c + e_w + q <= gamma
16059//
16060// or
16061//
16062// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
16063// <= f_c * f_w * 2^gamma
16064//
16065// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
16066//
16067// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
16068//
16069// or
16070//
16071// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
16072//
16073// The choice of (alpha,gamma) determines the size of the table and the form of
16074// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
16075// in practice:
16076//
16077// The idea is to cut the number c * w = f * 2^e into two parts, which can be
16078// processed independently: An integral part p1, and a fractional part p2:
16079//
16080// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
16081// = (f div 2^-e) + (f mod 2^-e) * 2^e
16082// = p1 + p2 * 2^e
16083//
16084// The conversion of p1 into decimal form requires a series of divisions and
16085// modulos by (a power of) 10. These operations are faster for 32-bit than for
16086// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
16087// achieved by choosing
16088//
16089// -e >= 32 or e <= -32 := gamma
16090//
16091// In order to convert the fractional part
16092//
16093// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
16094//
16095// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
16096// d[-i] are extracted in order:
16097//
16098// (10 * p2) div 2^-e = d[-1]
16099// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
16100//
16101// The multiplication by 10 must not overflow. It is sufficient to choose
16102//
16103// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
16104//
16105// Since p2 = f mod 2^-e < 2^-e,
16106//
16107// -e <= 60 or e >= -60 := alpha
16108
16109constexpr int kAlpha = -60;
16110constexpr int kGamma = -32;
16111
16112struct cached_power // c = f * 2^e ~= 10^k
16113{
16114 std::uint64_t f;
16115 int e;
16116 int k;
16117};
16118
16127 // Now
16128 //
16129 // alpha <= e_c + e + q <= gamma (1)
16130 // ==> f_c * 2^alpha <= c * 2^e * 2^q
16131 //
16132 // and since the c's are normalized, 2^(q-1) <= f_c,
16133 //
16134 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
16135 // ==> 2^(alpha - e - 1) <= c
16136 //
16137 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
16138 //
16139 // k = ceil( log_10( 2^(alpha - e - 1) ) )
16140 // = ceil( (alpha - e - 1) * log_10(2) )
16141 //
16142 // From the paper:
16143 // "In theory the result of the procedure could be wrong since c is rounded,
16144 // and the computation itself is approximated [...]. In practice, however,
16145 // this simple function is sufficient."
16146 //
16147 // For IEEE double precision floating-point numbers converted into
16148 // normalized diyfp's w = f * 2^e, with q = 64,
16149 //
16150 // e >= -1022 (min IEEE exponent)
16151 // -52 (p - 1)
16152 // -52 (p - 1, possibly normalize denormal IEEE numbers)
16153 // -11 (normalize the diyfp)
16154 // = -1137
16155 //
16156 // and
16157 //
16158 // e <= +1023 (max IEEE exponent)
16159 // -52 (p - 1)
16160 // -11 (normalize the diyfp)
16161 // = 960
16162 //
16163 // This binary exponent range [-1137,960] results in a decimal exponent
16164 // range [-307,324]. One does not need to store a cached power for each
16165 // k in this range. For each such k it suffices to find a cached power
16166 // such that the exponent of the product lies in [alpha,gamma].
16167 // This implies that the difference of the decimal exponents of adjacent
16168 // table entries must be less than or equal to
16169 //
16170 // floor( (gamma - alpha) * log_10(2) ) = 8.
16171 //
16172 // (A smaller distance gamma-alpha would require a larger table.)
16173
16174 // NB:
16175 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
16176
16177 constexpr int kCachedPowersMinDecExp = -300;
16178 constexpr int kCachedPowersDecStep = 8;
16179
16180 static constexpr std::array<cached_power, 79> kCachedPowers = {{
16181 {0xAB70FE17C79AC6CA, -1060, -300}, {0xFF77B1FCBEBCDC4F, -1034, -292},
16182 {0xBE5691EF416BD60C, -1007, -284}, {0x8DD01FAD907FFC3C, -980, -276},
16183 {0xD3515C2831559A83, -954, -268}, {0x9D71AC8FADA6C9B5, -927, -260},
16184 {0xEA9C227723EE8BCB, -901, -252}, {0xAECC49914078536D, -874, -244},
16185 {0x823C12795DB6CE57, -847, -236}, {0xC21094364DFB5637, -821, -228},
16186 {0x9096EA6F3848984F, -794, -220}, {0xD77485CB25823AC7, -768, -212},
16187 {0xA086CFCD97BF97F4, -741, -204}, {0xEF340A98172AACE5, -715, -196},
16188 {0xB23867FB2A35B28E, -688, -188}, {0x84C8D4DFD2C63F3B, -661, -180},
16189 {0xC5DD44271AD3CDBA, -635, -172}, {0x936B9FCEBB25C996, -608, -164},
16190 {0xDBAC6C247D62A584, -582, -156}, {0xA3AB66580D5FDAF6, -555, -148},
16191 {0xF3E2F893DEC3F126, -529, -140}, {0xB5B5ADA8AAFF80B8, -502, -132},
16192 {0x87625F056C7C4A8B, -475, -124}, {0xC9BCFF6034C13053, -449, -116},
16193 {0x964E858C91BA2655, -422, -108}, {0xDFF9772470297EBD, -396, -100},
16194 {0xA6DFBD9FB8E5B88F, -369, -92}, {0xF8A95FCF88747D94, -343, -84},
16195 {0xB94470938FA89BCF, -316, -76}, {0x8A08F0F8BF0F156B, -289, -68},
16196 {0xCDB02555653131B6, -263, -60}, {0x993FE2C6D07B7FAC, -236, -52},
16197 {0xE45C10C42A2B3B06, -210, -44}, {0xAA242499697392D3, -183, -36},
16198 {0xFD87B5F28300CA0E, -157, -28}, {0xBCE5086492111AEB, -130, -20},
16199 {0x8CBCCC096F5088CC, -103, -12}, {0xD1B71758E219652C, -77, -4},
16200 {0x9C40000000000000, -50, 4}, {0xE8D4A51000000000, -24, 12},
16201 {0xAD78EBC5AC620000, 3, 20}, {0x813F3978F8940984, 30, 28},
16202 {0xC097CE7BC90715B3, 56, 36}, {0x8F7E32CE7BEA5C70, 83, 44},
16203 {0xD5D238A4ABE98068, 109, 52}, {0x9F4F2726179A2245, 136, 60},
16204 {0xED63A231D4C4FB27, 162, 68}, {0xB0DE65388CC8ADA8, 189, 76},
16205 {0x83C7088E1AAB65DB, 216, 84}, {0xC45D1DF942711D9A, 242, 92},
16206 {0x924D692CA61BE758, 269, 100}, {0xDA01EE641A708DEA, 295, 108},
16207 {0xA26DA3999AEF774A, 322, 116}, {0xF209787BB47D6B85, 348, 124},
16208 {0xB454E4A179DD1877, 375, 132}, {0x865B86925B9BC5C2, 402, 140},
16209 {0xC83553C5C8965D3D, 428, 148}, {0x952AB45CFA97A0B3, 455, 156},
16210 {0xDE469FBD99A05FE3, 481, 164}, {0xA59BC234DB398C25, 508, 172},
16211 {0xF6C69A72A3989F5C, 534, 180}, {0xB7DCBF5354E9BECE, 561, 188},
16212 {0x88FCF317F22241E2, 588, 196}, {0xCC20CE9BD35C78A5, 614, 204},
16213 {0x98165AF37B2153DF, 641, 212}, {0xE2A0B5DC971F303A, 667, 220},
16214 {0xA8D9D1535CE3B396, 694, 228}, {0xFB9B7CD9A4A7443C, 720, 236},
16215 {0xBB764C4CA7A44410, 747, 244}, {0x8BAB8EEFB6409C1A, 774, 252},
16216 {0xD01FEF10A657842C, 800, 260}, {0x9B10A4E5E9913129, 827, 268},
16217 {0xE7109BFBA19C0C9D, 853, 276}, {0xAC2820D9623BF429, 880, 284},
16218 {0x80444B5E7AA7CF85, 907, 292}, {0xBF21E44003ACDD2D, 933, 300},
16219 {0x8E679C2F5E44FF8F, 960, 308}, {0xD433179D9C8CB841, 986, 316},
16220 {0x9E19DB92B4E31BA9, 1013, 324},
16221 }};
16222
16223 // This computation gives exactly the same results for k as
16224 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
16225 // for |e| <= 1500, but doesn't require floating-point operations.
16226 // NB: log_10(2) ~= 78913 / 2^18
16227 JSON_ASSERT(e >= -1500);
16228 JSON_ASSERT(e <= 1500);
16229 const int f = kAlpha - e - 1;
16230 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
16231
16232 const int index =
16233 (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
16234 JSON_ASSERT(index >= 0);
16235 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
16236
16237 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
16238 JSON_ASSERT(kAlpha <= cached.e + e + 64);
16239 JSON_ASSERT(kGamma >= cached.e + e + 64);
16240
16241 return cached;
16242}
16243
16248inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) {
16249 // LCOV_EXCL_START
16250 if (n >= 1000000000) {
16251 pow10 = 1000000000;
16252 return 10;
16253 }
16254 // LCOV_EXCL_STOP
16255 if (n >= 100000000) {
16256 pow10 = 100000000;
16257 return 9;
16258 }
16259 if (n >= 10000000) {
16260 pow10 = 10000000;
16261 return 8;
16262 }
16263 if (n >= 1000000) {
16264 pow10 = 1000000;
16265 return 7;
16266 }
16267 if (n >= 100000) {
16268 pow10 = 100000;
16269 return 6;
16270 }
16271 if (n >= 10000) {
16272 pow10 = 10000;
16273 return 5;
16274 }
16275 if (n >= 1000) {
16276 pow10 = 1000;
16277 return 4;
16278 }
16279 if (n >= 100) {
16280 pow10 = 100;
16281 return 3;
16282 }
16283 if (n >= 10) {
16284 pow10 = 10;
16285 return 2;
16286 }
16287
16288 pow10 = 1;
16289 return 1;
16290}
16291
16292inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
16293 std::uint64_t rest, std::uint64_t ten_k) {
16294 JSON_ASSERT(len >= 1);
16295 JSON_ASSERT(dist <= delta);
16296 JSON_ASSERT(rest <= delta);
16297 JSON_ASSERT(ten_k > 0);
16298
16299 // <--------------------------- delta ---->
16300 // <---- dist --------->
16301 // --------------[------------------+-------------------]--------------
16302 // M- w M+
16303 //
16304 // ten_k
16305 // <------>
16306 // <---- rest ---->
16307 // --------------[------------------+----+--------------]--------------
16308 // w V
16309 // = buf * 10^k
16310 //
16311 // ten_k represents a unit-in-the-last-place in the decimal representation
16312 // stored in buf.
16313 // Decrement buf by ten_k while this takes buf closer to w.
16314
16315 // The tests are written in this order to avoid overflow in unsigned
16316 // integer arithmetic.
16317
16318 while (rest < dist && delta - rest >= ten_k &&
16319 (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) {
16320 JSON_ASSERT(buf[len - 1] != '0');
16321 buf[len - 1]--;
16322 rest += ten_k;
16323 }
16324}
16325
16330inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, diyfp M_minus,
16331 diyfp w, diyfp M_plus) {
16332 static_assert(kAlpha >= -60, "internal error");
16333 static_assert(kGamma <= -32, "internal error");
16334
16335 // Generates the digits (and the exponent) of a decimal floating-point
16336 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
16337 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <=
16338 // gamma.
16339 //
16340 // <--------------------------- delta ---->
16341 // <---- dist --------->
16342 // --------------[------------------+-------------------]--------------
16343 // M- w M+
16344 //
16345 // Grisu2 generates the digits of M+ from left to right and stops as soon as
16346 // V is in [M-,M+].
16347
16348 JSON_ASSERT(M_plus.e >= kAlpha);
16349 JSON_ASSERT(M_plus.e <= kGamma);
16350
16351 std::uint64_t delta =
16352 diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
16353 std::uint64_t dist =
16354 diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
16355
16356 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
16357 //
16358 // M+ = f * 2^e
16359 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
16360 // = ((p1 ) * 2^-e + (p2 )) * 2^e
16361 // = p1 + p2 * 2^e
16362
16363 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
16364
16365 auto p1 = static_cast<std::uint32_t>(
16366 M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
16367 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
16368
16369 // 1)
16370 //
16371 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
16372
16373 JSON_ASSERT(p1 > 0);
16374
16375 std::uint32_t pow10{};
16376 const int k = find_largest_pow10(p1, pow10);
16377
16378 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
16379 //
16380 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
16381 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
16382 //
16383 // M+ = p1 + p2 * 2^e
16384 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
16385 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
16386 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
16387 //
16388 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
16389 //
16390 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
16391 //
16392 // but stop as soon as
16393 //
16394 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
16395
16396 int n = k;
16397 while (n > 0) {
16398 // Invariants:
16399 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
16400 // pow10 = 10^(n-1) <= p1 < 10^n
16401 //
16402 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
16403 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
16404 //
16405 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
16406 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
16407 //
16408 JSON_ASSERT(d <= 9);
16409 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16410 //
16411 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
16412 //
16413 p1 = r;
16414 n--;
16415 //
16416 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
16417 // pow10 = 10^n
16418 //
16419
16420 // Now check if enough digits have been generated.
16421 // Compute
16422 //
16423 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
16424 //
16425 // Note:
16426 // Since rest and delta share the same exponent e, it suffices to
16427 // compare the significands.
16428 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
16429 if (rest <= delta) {
16430 // V = buffer * 10^n, with M- <= V <= M+.
16431
16432 decimal_exponent += n;
16433
16434 // We may now just stop. But instead look if the buffer could be
16435 // decremented to bring V closer to w.
16436 //
16437 // pow10 = 10^n is now 1 ulp in the decimal representation V.
16438 // The rounding procedure works with diyfp's with an implicit
16439 // exponent of e.
16440 //
16441 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
16442 //
16443 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
16444 grisu2_round(buffer, length, dist, delta, rest, ten_n);
16445
16446 return;
16447 }
16448
16449 pow10 /= 10;
16450 //
16451 // pow10 = 10^(n-1) <= p1 < 10^n
16452 // Invariants restored.
16453 }
16454
16455 // 2)
16456 //
16457 // The digits of the integral part have been generated:
16458 //
16459 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
16460 // = buffer + p2 * 2^e
16461 //
16462 // Now generate the digits of the fractional part p2 * 2^e.
16463 //
16464 // Note:
16465 // No decimal point is generated: the exponent is adjusted instead.
16466 //
16467 // p2 actually represents the fraction
16468 //
16469 // p2 * 2^e
16470 // = p2 / 2^-e
16471 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
16472 //
16473 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
16474 //
16475 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
16476 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
16477 //
16478 // using
16479 //
16480 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
16481 // = ( d) * 2^-e + ( r)
16482 //
16483 // or
16484 // 10^m * p2 * 2^e = d + r * 2^e
16485 //
16486 // i.e.
16487 //
16488 // M+ = buffer + p2 * 2^e
16489 // = buffer + 10^-m * (d + r * 2^e)
16490 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
16491 //
16492 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
16493
16494 JSON_ASSERT(p2 > delta);
16495
16496 int m = 0;
16497 for (;;) {
16498 // Invariant:
16499 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...)
16500 // * 2^e
16501 // = buffer * 10^-m + 10^-m * (p2 )
16502 // * 2^e = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e =
16503 // buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e +
16504 // (10*p2 mod 2^-e)) * 2^e
16505 //
16506 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
16507 p2 *= 10;
16508 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
16509 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
16510 //
16511 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
16512 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
16513 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
16514 //
16515 JSON_ASSERT(d <= 9);
16516 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
16517 //
16518 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
16519 //
16520 p2 = r;
16521 m++;
16522 //
16523 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
16524 // Invariant restored.
16525
16526 // Check if enough digits have been generated.
16527 //
16528 // 10^-m * p2 * 2^e <= delta * 2^e
16529 // p2 * 2^e <= 10^m * delta * 2^e
16530 // p2 <= 10^m * delta
16531 delta *= 10;
16532 dist *= 10;
16533 if (p2 <= delta) {
16534 break;
16535 }
16536 }
16537
16538 // V = buffer * 10^-m, with M- <= V <= M+.
16539
16540 decimal_exponent -= m;
16541
16542 // 1 ulp in the decimal representation is now 10^-m.
16543 // Since delta and dist are now scaled by 10^m, we need to do the
16544 // same with ulp in order to keep the units in sync.
16545 //
16546 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
16547 //
16548 const std::uint64_t ten_m = one.f;
16549 grisu2_round(buffer, length, dist, delta, p2, ten_m);
16550
16551 // By construction this algorithm generates the shortest possible decimal
16552 // number (Loitsch, Theorem 6.2) which rounds back to w.
16553 // For an input number of precision p, at least
16554 //
16555 // N = 1 + ceil(p * log_10(2))
16556 //
16557 // decimal digits are sufficient to identify all binary floating-point
16558 // numbers (Matula, "In-and-Out conversions").
16559 // This implies that the algorithm does not produce more than N decimal
16560 // digits.
16561 //
16562 // N = 17 for p = 53 (IEEE double precision)
16563 // N = 9 for p = 24 (IEEE single precision)
16564}
16565
16571JSON_HEDLEY_NON_NULL(1)
16572inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v,
16573 diyfp m_plus) {
16574 JSON_ASSERT(m_plus.e == m_minus.e);
16575 JSON_ASSERT(m_plus.e == v.e);
16576
16577 // --------(-----------------------+-----------------------)-------- (A)
16578 // m- v m+
16579 //
16580 // --------------------(-----------+-----------------------)-------- (B)
16581 // m- v m+
16582 //
16583 // First scale v (and m- and m+) such that the exponent is in the range
16584 // [alpha, gamma].
16585
16586 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
16587
16588 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
16589
16590 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range
16591 // [alpha,gamma]
16592 const diyfp w = diyfp::mul(v, c_minus_k);
16593 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
16594 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
16595
16596 // ----(---+---)---------------(---+---)---------------(---+---)----
16597 // w- w w+
16598 // = c*m- = c*v = c*m+
16599 //
16600 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
16601 // w+ are now off by a small amount.
16602 // In fact:
16603 //
16604 // w - v * 10^k < 1 ulp
16605 //
16606 // To account for this inaccuracy, add resp. subtract 1 ulp.
16607 //
16608 // --------+---[---------------(---+---)---------------]---+--------
16609 // w- M- w M+ w+
16610 //
16611 // Now any number in [M-, M+] (bounds included) will round to w when input,
16612 // regardless of how the input rounding algorithm breaks ties.
16613 //
16614 // And digit_gen generates the shortest possible such number in [M-, M+].
16615 // Note that this does not mean that Grisu2 always generates the shortest
16616 // possible number in the interval (m-, m+).
16617 const diyfp M_minus(w_minus.f + 1, w_minus.e);
16618 const diyfp M_plus(w_plus.f - 1, w_plus.e);
16619
16620 decimal_exponent = -cached.k; // = -(-k) = k
16621
16622 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
16623}
16624
16630template <typename FloatType>
16631JSON_HEDLEY_NON_NULL(1)
16632void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) {
16633 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
16634 "internal error: not enough precision");
16635
16636 JSON_ASSERT(std::isfinite(value));
16637 JSON_ASSERT(value > 0);
16638
16639 // If the neighbors (and boundaries) of 'value' are always computed for
16640 // double-precision numbers, all float's can be recovered using strtod (and
16641 // strtof). However, the resulting decimal representations are not exactly
16642 // "short".
16643 //
16644 // The documentation for 'std::to_chars'
16645 // (https://en.cppreference.com/w/cpp/utility/to_chars) says "value is
16646 // converted to a string as if by std::sprintf in the default ("C") locale"
16647 // and since sprintf promotes floats to doubles, I think this is exactly what
16648 // 'std::to_chars' does. On the other hand, the documentation for
16649 // 'std::to_chars' requires that "parsing the representation using the
16650 // corresponding std::from_chars function recovers value exactly". That
16651 // indicates that single precision floating-point numbers should be recovered
16652 // using 'std::strtof'.
16653 //
16654 // NB: If the neighbors are computed for single-precision numbers, there is a
16655 // single float
16656 // (7.0385307e-26f) which can't be recovered using strtod. The resulting
16657 // double precision value is off by 1 ulp.
16658#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
16659 const boundaries w = compute_boundaries(static_cast<double>(value));
16660#else
16661 const boundaries w = compute_boundaries(value);
16662#endif
16663
16664 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
16665}
16666
16672JSON_HEDLEY_NON_NULL(1)
16673JSON_HEDLEY_RETURNS_NON_NULL
16674inline char* append_exponent(char* buf, int e) {
16675 JSON_ASSERT(e > -1000);
16676 JSON_ASSERT(e < 1000);
16677
16678 if (e < 0) {
16679 e = -e;
16680 *buf++ = '-';
16681 } else {
16682 *buf++ = '+';
16683 }
16684
16685 auto k = static_cast<std::uint32_t>(e);
16686 if (k < 10) {
16687 // Always print at least two digits in the exponent.
16688 // This is for compatibility with printf("%g").
16689 *buf++ = '0';
16690 *buf++ = static_cast<char>('0' + k);
16691 } else if (k < 100) {
16692 *buf++ = static_cast<char>('0' + k / 10);
16693 k %= 10;
16694 *buf++ = static_cast<char>('0' + k);
16695 } else {
16696 *buf++ = static_cast<char>('0' + k / 100);
16697 k %= 100;
16698 *buf++ = static_cast<char>('0' + k / 10);
16699 k %= 10;
16700 *buf++ = static_cast<char>('0' + k);
16701 }
16702
16703 return buf;
16704}
16705
16715JSON_HEDLEY_NON_NULL(1)
16716JSON_HEDLEY_RETURNS_NON_NULL
16717inline char* format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp) {
16718 JSON_ASSERT(min_exp < 0);
16719 JSON_ASSERT(max_exp > 0);
16720
16721 const int k = len;
16722 const int n = len + decimal_exponent;
16723
16724 // v = buf * 10^(n-k)
16725 // k is the length of the buffer (number of decimal digits)
16726 // n is the position of the decimal point relative to the start of the buffer.
16727
16728 if (k <= n && n <= max_exp) {
16729 // digits[000]
16730 // len <= max_exp + 2
16731
16732 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
16733 // Make it look like a floating-point number (#362, #378)
16734 buf[n + 0] = '.';
16735 buf[n + 1] = '0';
16736 return buf + (static_cast<size_t>(n) + 2);
16737 }
16738
16739 if (0 < n && n <= max_exp) {
16740 // dig.its
16741 // len <= max_digits10 + 1
16742
16743 JSON_ASSERT(k > n);
16744
16745 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n,
16746 static_cast<size_t>(k) - static_cast<size_t>(n));
16747 buf[n] = '.';
16748 return buf + (static_cast<size_t>(k) + 1U);
16749 }
16750
16751 if (min_exp < n && n <= 0) {
16752 // 0.[000]digits
16753 // len <= 2 + (-min_exp - 1) + max_digits10
16754
16755 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
16756 buf[0] = '0';
16757 buf[1] = '.';
16758 std::memset(buf + 2, '0', static_cast<size_t>(-n));
16759 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
16760 }
16761
16762 if (k == 1) {
16763 // dE+123
16764 // len <= 1 + 5
16765
16766 buf += 1;
16767 } else {
16768 // d.igitsE+123
16769 // len <= max_digits10 + 1 + 5
16770
16771 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
16772 buf[1] = '.';
16773 buf += 1 + static_cast<size_t>(k);
16774 }
16775
16776 *buf++ = 'e';
16777 return append_exponent(buf, n - 1);
16778}
16779
16780} // namespace dtoa_impl
16781
16793template <typename FloatType>
16794JSON_HEDLEY_NON_NULL(1, 2)
16795JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, FloatType value) {
16796 static_cast<void>(last); // maybe unused - fix warning
16797 JSON_ASSERT(std::isfinite(value));
16798
16799 // Use signbit(value) instead of (value < 0) since signbit works for -0.
16800 if (std::signbit(value)) {
16801 value = -value;
16802 *first++ = '-';
16803 }
16804
16805#ifdef __GNUC__
16806#pragma GCC diagnostic push
16807#pragma GCC diagnostic ignored "-Wfloat-equal"
16808#endif
16809 if (value == 0) // +-0
16810 {
16811 *first++ = '0';
16812 // Make it look like a floating-point number (#362, #378)
16813 *first++ = '.';
16814 *first++ = '0';
16815 return first;
16816 }
16817#ifdef __GNUC__
16818#pragma GCC diagnostic pop
16819#endif
16820
16821 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
16822
16823 // Compute v = buffer * 10^decimal_exponent.
16824 // The decimal digits are stored in the buffer, which needs to be interpreted
16825 // as an unsigned decimal integer.
16826 // len is the length of the buffer, i.e. the number of decimal digits.
16827 int len = 0;
16828 int decimal_exponent = 0;
16829 dtoa_impl::grisu2(first, len, decimal_exponent, value);
16830
16831 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
16832
16833 // Format the buffer like printf("%.*g", prec, value)
16834 constexpr int kMinExp = -4;
16835 // Use digits10 here to increase compatibility with version 2.
16836 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
16837
16838 JSON_ASSERT(last - first >= kMaxExp + 2);
16839 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
16840 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
16841
16842 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
16843}
16844
16845} // namespace detail
16846NLOHMANN_JSON_NAMESPACE_END
16847
16848// #include <nlohmann/detail/exceptions.hpp>
16849
16850// #include <nlohmann/detail/macro_scope.hpp>
16851
16852// #include <nlohmann/detail/meta/cpp_future.hpp>
16853
16854// #include <nlohmann/detail/output/binary_writer.hpp>
16855
16856// #include <nlohmann/detail/output/output_adapters.hpp>
16857
16858// #include <nlohmann/detail/string_concat.hpp>
16859
16860// #include <nlohmann/detail/value_t.hpp>
16861
16862NLOHMANN_JSON_NAMESPACE_BEGIN
16863namespace detail {
16864
16866// serialization //
16868
16875
16876template <typename BasicJsonType> class serializer {
16877 using string_t = typename BasicJsonType::string_t;
16878 using number_float_t = typename BasicJsonType::number_float_t;
16879 using number_integer_t = typename BasicJsonType::number_integer_t;
16880 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
16881 using binary_char_t = typename BasicJsonType::binary_t::value_type;
16882 static constexpr std::uint8_t UTF8_ACCEPT = 0;
16883 static constexpr std::uint8_t UTF8_REJECT = 1;
16884
16885 public:
16893 : o(std::move(s)), loc(std::localeconv()),
16894 thousands_sep(loc->thousands_sep == nullptr
16895 ? '\0'
16896 : std::char_traits<char>::to_char_type(*(loc->thousands_sep))),
16897 decimal_point(loc->decimal_point == nullptr
16898 ? '\0'
16899 : std::char_traits<char>::to_char_type(*(loc->decimal_point))),
16900 indent_char(ichar), indent_string(512, indent_char), error_handler(error_handler_) {}
16901
16902 // delete because of pointer members
16903 serializer(const serializer&) = delete;
16904 serializer& operator=(const serializer&) = delete;
16905 serializer(serializer&&) = delete;
16906 serializer& operator=(serializer&&) = delete;
16907 ~serializer() = default;
16908
16931 void dump(const BasicJsonType& val, const bool pretty_print, const bool ensure_ascii,
16932 const unsigned int indent_step, const unsigned int current_indent = 0) {
16933 switch (val.m_data.m_type) {
16934 case value_t::object: {
16935 if (val.m_data.m_value.object->empty()) {
16936 o->write_characters("{}", 2);
16937 return;
16938 }
16939
16940 if (pretty_print) {
16941 o->write_characters("{\n", 2);
16942
16943 // variable to hold indentation for recursive calls
16944 const auto new_indent = current_indent + indent_step;
16945 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
16946 indent_string.resize(indent_string.size() * 2, ' ');
16947 }
16948
16949 // first n-1 elements
16950 auto i = val.m_data.m_value.object->cbegin();
16951 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1;
16952 ++cnt, ++i) {
16953 o->write_characters(indent_string.c_str(), new_indent);
16954 o->write_character('\"');
16955 dump_escaped(i->first, ensure_ascii);
16956 o->write_characters("\": ", 3);
16957 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16958 o->write_characters(",\n", 2);
16959 }
16960
16961 // last element
16962 JSON_ASSERT(i != val.m_data.m_value.object->cend());
16963 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
16964 o->write_characters(indent_string.c_str(), new_indent);
16965 o->write_character('\"');
16966 dump_escaped(i->first, ensure_ascii);
16967 o->write_characters("\": ", 3);
16968 dump(i->second, true, ensure_ascii, indent_step, new_indent);
16969
16970 o->write_character('\n');
16971 o->write_characters(indent_string.c_str(), current_indent);
16972 o->write_character('}');
16973 } else {
16974 o->write_character('{');
16975
16976 // first n-1 elements
16977 auto i = val.m_data.m_value.object->cbegin();
16978 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1;
16979 ++cnt, ++i) {
16980 o->write_character('\"');
16981 dump_escaped(i->first, ensure_ascii);
16982 o->write_characters("\":", 2);
16983 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16984 o->write_character(',');
16985 }
16986
16987 // last element
16988 JSON_ASSERT(i != val.m_data.m_value.object->cend());
16989 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
16990 o->write_character('\"');
16991 dump_escaped(i->first, ensure_ascii);
16992 o->write_characters("\":", 2);
16993 dump(i->second, false, ensure_ascii, indent_step, current_indent);
16994
16995 o->write_character('}');
16996 }
16997
16998 return;
16999 }
17000
17001 case value_t::array: {
17002 if (val.m_data.m_value.array->empty()) {
17003 o->write_characters("[]", 2);
17004 return;
17005 }
17006
17007 if (pretty_print) {
17008 o->write_characters("[\n", 2);
17009
17010 // variable to hold indentation for recursive calls
17011 const auto new_indent = current_indent + indent_step;
17012 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17013 indent_string.resize(indent_string.size() * 2, ' ');
17014 }
17015
17016 // first n-1 elements
17017 for (auto i = val.m_data.m_value.array->cbegin();
17018 i != val.m_data.m_value.array->cend() - 1; ++i) {
17019 o->write_characters(indent_string.c_str(), new_indent);
17020 dump(*i, true, ensure_ascii, indent_step, new_indent);
17021 o->write_characters(",\n", 2);
17022 }
17023
17024 // last element
17025 JSON_ASSERT(!val.m_data.m_value.array->empty());
17026 o->write_characters(indent_string.c_str(), new_indent);
17027 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step,
17028 new_indent);
17029
17030 o->write_character('\n');
17031 o->write_characters(indent_string.c_str(), current_indent);
17032 o->write_character(']');
17033 } else {
17034 o->write_character('[');
17035
17036 // first n-1 elements
17037 for (auto i = val.m_data.m_value.array->cbegin();
17038 i != val.m_data.m_value.array->cend() - 1; ++i) {
17039 dump(*i, false, ensure_ascii, indent_step, current_indent);
17040 o->write_character(',');
17041 }
17042
17043 // last element
17044 JSON_ASSERT(!val.m_data.m_value.array->empty());
17045 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step,
17046 current_indent);
17047
17048 o->write_character(']');
17049 }
17050
17051 return;
17052 }
17053
17054 case value_t::string: {
17055 o->write_character('\"');
17056 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
17057 o->write_character('\"');
17058 return;
17059 }
17060
17061 case value_t::binary: {
17062 if (pretty_print) {
17063 o->write_characters("{\n", 2);
17064
17065 // variable to hold indentation for recursive calls
17066 const auto new_indent = current_indent + indent_step;
17067 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17068 indent_string.resize(indent_string.size() * 2, ' ');
17069 }
17070
17071 o->write_characters(indent_string.c_str(), new_indent);
17072
17073 o->write_characters("\"bytes\": [", 10);
17074
17075 if (!val.m_data.m_value.binary->empty()) {
17076 for (auto i = val.m_data.m_value.binary->cbegin();
17077 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17078 dump_integer(*i);
17079 o->write_characters(", ", 2);
17080 }
17081 dump_integer(val.m_data.m_value.binary->back());
17082 }
17083
17084 o->write_characters("],\n", 3);
17085 o->write_characters(indent_string.c_str(), new_indent);
17086
17087 o->write_characters("\"subtype\": ", 11);
17088 if (val.m_data.m_value.binary->has_subtype()) {
17089 dump_integer(val.m_data.m_value.binary->subtype());
17090 } else {
17091 o->write_characters("null", 4);
17092 }
17093 o->write_character('\n');
17094 o->write_characters(indent_string.c_str(), current_indent);
17095 o->write_character('}');
17096 } else {
17097 o->write_characters("{\"bytes\":[", 10);
17098
17099 if (!val.m_data.m_value.binary->empty()) {
17100 for (auto i = val.m_data.m_value.binary->cbegin();
17101 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17102 dump_integer(*i);
17103 o->write_character(',');
17104 }
17105 dump_integer(val.m_data.m_value.binary->back());
17106 }
17107
17108 o->write_characters("],\"subtype\":", 12);
17109 if (val.m_data.m_value.binary->has_subtype()) {
17110 dump_integer(val.m_data.m_value.binary->subtype());
17111 o->write_character('}');
17112 } else {
17113 o->write_characters("null}", 5);
17114 }
17115 }
17116 return;
17117 }
17118
17119 case value_t::boolean: {
17120 if (val.m_data.m_value.boolean) {
17121 o->write_characters("true", 4);
17122 } else {
17123 o->write_characters("false", 5);
17124 }
17125 return;
17126 }
17127
17129 dump_integer(val.m_data.m_value.number_integer);
17130 return;
17131 }
17132
17134 dump_integer(val.m_data.m_value.number_unsigned);
17135 return;
17136 }
17137
17138 case value_t::number_float: {
17139 dump_float(val.m_data.m_value.number_float);
17140 return;
17141 }
17142
17143 case value_t::discarded: {
17144 o->write_characters("<discarded>", 11);
17145 return;
17146 }
17147
17148 case value_t::null: {
17149 o->write_characters("null", 4);
17150 return;
17151 }
17152
17153 default: // LCOV_EXCL_LINE
17154 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17155 // LCOV_EXCL_LINE
17156 }
17157 }
17158
17159 JSON_PRIVATE_UNLESS_TESTED :
17174 void
17175 dump_escaped(const string_t& s, const bool ensure_ascii) {
17176 std::uint32_t codepoint{};
17177 std::uint8_t state = UTF8_ACCEPT;
17178 std::size_t bytes = 0; // number of bytes written to string_buffer
17179
17180 // number of bytes written at the point of the last valid byte
17181 std::size_t bytes_after_last_accept = 0;
17182 std::size_t undumped_chars = 0;
17183
17184 for (std::size_t i = 0; i < s.size(); ++i) {
17185 const auto byte = static_cast<std::uint8_t>(s[i]);
17186
17187 switch (decode(state, codepoint, byte)) {
17188 case UTF8_ACCEPT: // decode found a new code point
17189 {
17190 switch (codepoint) {
17191 case 0x08: // backspace
17192 {
17193 string_buffer[bytes++] = '\\';
17194 string_buffer[bytes++] = 'b';
17195 break;
17196 }
17197
17198 case 0x09: // horizontal tab
17199 {
17200 string_buffer[bytes++] = '\\';
17201 string_buffer[bytes++] = 't';
17202 break;
17203 }
17204
17205 case 0x0A: // newline
17206 {
17207 string_buffer[bytes++] = '\\';
17208 string_buffer[bytes++] = 'n';
17209 break;
17210 }
17211
17212 case 0x0C: // formfeed
17213 {
17214 string_buffer[bytes++] = '\\';
17215 string_buffer[bytes++] = 'f';
17216 break;
17217 }
17218
17219 case 0x0D: // carriage return
17220 {
17221 string_buffer[bytes++] = '\\';
17222 string_buffer[bytes++] = 'r';
17223 break;
17224 }
17225
17226 case 0x22: // quotation mark
17227 {
17228 string_buffer[bytes++] = '\\';
17229 string_buffer[bytes++] = '\"';
17230 break;
17231 }
17232
17233 case 0x5C: // reverse solidus
17234 {
17235 string_buffer[bytes++] = '\\';
17236 string_buffer[bytes++] = '\\';
17237 break;
17238 }
17239
17240 default: {
17241 // escape control characters (0x00..0x1F) or, if
17242 // ensure_ascii parameter is used, non-ASCII characters
17243 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) {
17244 if (codepoint <= 0xFFFF) {
17245 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17246 static_cast<void>(
17247 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
17248 static_cast<std::uint16_t>(codepoint)));
17249 bytes += 6;
17250 } else {
17251 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17252 static_cast<void>((std::snprintf)(
17253 string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
17254 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
17255 static_cast<std::uint16_t>(0xDC00u +
17256 (codepoint & 0x3FFu))));
17257 bytes += 12;
17258 }
17259 } else {
17260 // copy byte to buffer (all previous bytes
17261 // been copied have in default case above)
17262 string_buffer[bytes++] = s[i];
17263 }
17264 break;
17265 }
17266 }
17267
17268 // write buffer and reset index; there must be 13 bytes
17269 // left, as this is the maximal number of bytes to be
17270 // written ("\uxxxx\uxxxx\0") for one code point
17271 if (string_buffer.size() - bytes < 13) {
17272 o->write_characters(string_buffer.data(), bytes);
17273 bytes = 0;
17274 }
17275
17276 // remember the byte position of this accept
17277 bytes_after_last_accept = bytes;
17278 undumped_chars = 0;
17279 break;
17280 }
17281
17282 case UTF8_REJECT: // decode found invalid UTF-8 byte
17283 {
17284 switch (error_handler) {
17285 case error_handler_t::strict: {
17286 JSON_THROW(type_error::create(316,
17287 concat("invalid UTF-8 byte at index ",
17288 std::to_string(i), ": 0x",
17289 hex_bytes(byte | 0)),
17290 nullptr));
17291 }
17292
17293 case error_handler_t::ignore:
17294 case error_handler_t::replace: {
17295 // in case we saw this character the first time, we
17296 // would like to read it again, because the byte
17297 // may be OK for itself, but just not OK for the
17298 // previous sequence
17299 if (undumped_chars > 0) {
17300 --i;
17301 }
17302
17303 // reset length buffer to the last accepted index;
17304 // thus removing/ignoring the invalid characters
17305 bytes = bytes_after_last_accept;
17306
17307 if (error_handler == error_handler_t::replace) {
17308 // add a replacement character
17309 if (ensure_ascii) {
17310 string_buffer[bytes++] = '\\';
17311 string_buffer[bytes++] = 'u';
17312 string_buffer[bytes++] = 'f';
17313 string_buffer[bytes++] = 'f';
17314 string_buffer[bytes++] = 'f';
17315 string_buffer[bytes++] = 'd';
17316 } else {
17317 string_buffer[bytes++] =
17318 detail::binary_writer<BasicJsonType, char>::to_char_type(
17319 '\xEF');
17320 string_buffer[bytes++] =
17321 detail::binary_writer<BasicJsonType, char>::to_char_type(
17322 '\xBF');
17323 string_buffer[bytes++] =
17324 detail::binary_writer<BasicJsonType, char>::to_char_type(
17325 '\xBD');
17326 }
17327
17328 // write buffer and reset index; there must be 13 bytes
17329 // left, as this is the maximal number of bytes to be
17330 // written ("\uxxxx\uxxxx\0") for one code point
17331 if (string_buffer.size() - bytes < 13) {
17332 o->write_characters(string_buffer.data(), bytes);
17333 bytes = 0;
17334 }
17335
17336 bytes_after_last_accept = bytes;
17337 }
17338
17339 undumped_chars = 0;
17340
17341 // continue processing the string
17342 state = UTF8_ACCEPT;
17343 break;
17344 }
17345
17346 default: // LCOV_EXCL_LINE
17347 JSON_ASSERT(
17348 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17349 // LCOV_EXCL_LINE
17350 }
17351 break;
17352 }
17353
17354 default: // decode found yet incomplete multi-byte code point
17355 {
17356 if (!ensure_ascii) {
17357 // code point will not be escaped - copy byte to buffer
17358 string_buffer[bytes++] = s[i];
17359 }
17360 ++undumped_chars;
17361 break;
17362 }
17363 }
17364 }
17365
17366 // we finished processing the string
17367 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) {
17368 // write buffer
17369 if (bytes > 0) {
17370 o->write_characters(string_buffer.data(), bytes);
17371 }
17372 } else {
17373 // we finish reading, but do not accept: string was incomplete
17374 switch (error_handler) {
17375 case error_handler_t::strict: {
17376 JSON_THROW(type_error::create(
17377 316,
17378 concat("incomplete UTF-8 string; last byte: 0x",
17379 hex_bytes(static_cast<std::uint8_t>(s.back() | 0))),
17380 nullptr));
17381 }
17382
17383 case error_handler_t::ignore: {
17384 // write all accepted bytes
17385 o->write_characters(string_buffer.data(), bytes_after_last_accept);
17386 break;
17387 }
17388
17389 case error_handler_t::replace: {
17390 // write all accepted bytes
17391 o->write_characters(string_buffer.data(), bytes_after_last_accept);
17392 // add a replacement character
17393 if (ensure_ascii) {
17394 o->write_characters("\\ufffd", 6);
17395 } else {
17396 o->write_characters("\xEF\xBF\xBD", 3);
17397 }
17398 break;
17399 }
17400
17401 default: // LCOV_EXCL_LINE
17402 JSON_ASSERT(
17403 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17404 // LCOV_EXCL_LINE
17405 }
17406 }
17407 }
17408
17409 private:
17418 inline unsigned int count_digits(number_unsigned_t x) noexcept {
17419 unsigned int n_digits = 1;
17420 for (;;) {
17421 if (x < 10) {
17422 return n_digits;
17423 }
17424 if (x < 100) {
17425 return n_digits + 1;
17426 }
17427 if (x < 1000) {
17428 return n_digits + 2;
17429 }
17430 if (x < 10000) {
17431 return n_digits + 3;
17432 }
17433 x = x / 10000u;
17434 n_digits += 4;
17435 }
17436 }
17437
17443 static std::string hex_bytes(std::uint8_t byte) {
17444 std::string result = "FF";
17445 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
17446 result[0] = nibble_to_hex[byte / 16];
17447 result[1] = nibble_to_hex[byte % 16];
17448 return result;
17449 }
17450
17451 // templates to avoid warnings about useless casts
17452 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
17453 bool is_negative_number(NumberType x) {
17454 return x < 0;
17455 }
17456
17457 template <typename NumberType, enable_if_t<std::is_unsigned<NumberType>::value, int> = 0>
17458 bool is_negative_number(NumberType /*unused*/) {
17459 return false;
17460 }
17461
17471 template <typename NumberType,
17472 detail::enable_if_t<std::is_integral<NumberType>::value ||
17473 std::is_same<NumberType, number_unsigned_t>::value ||
17474 std::is_same<NumberType, number_integer_t>::value ||
17475 std::is_same<NumberType, binary_char_t>::value,
17476 int> = 0>
17477 void dump_integer(NumberType x) {
17478 static constexpr std::array<std::array<char, 2>, 100> digits_to_99{{
17479 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}},
17480 {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, {{'1', '0'}}, {{'1', '1'}},
17481 {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}},
17482 {{'1', '8'}}, {{'1', '9'}}, {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}},
17483 {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
17484 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}},
17485 {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, {{'4', '0'}}, {{'4', '1'}},
17486 {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}},
17487 {{'4', '8'}}, {{'4', '9'}}, {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}},
17488 {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
17489 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}},
17490 {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, {{'7', '0'}}, {{'7', '1'}},
17491 {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}},
17492 {{'7', '8'}}, {{'7', '9'}}, {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}},
17493 {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
17494 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}},
17495 {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
17496 }};
17497
17498 // special case for "0"
17499 if (x == 0) {
17500 o->write_character('0');
17501 return;
17502 }
17503
17504 // use a pointer to fill the buffer
17505 auto buffer_ptr =
17506 number_buffer
17507 .begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17508
17509 number_unsigned_t abs_value;
17510
17511 unsigned int n_chars{};
17512
17513 if (is_negative_number(x)) {
17514 *buffer_ptr = '-';
17515 abs_value = remove_sign(static_cast<number_integer_t>(x));
17516
17517 // account one more byte for the minus sign
17518 n_chars = 1 + count_digits(abs_value);
17519 } else {
17520 abs_value = static_cast<number_unsigned_t>(x);
17521 n_chars = count_digits(abs_value);
17522 }
17523
17524 // spare 1 byte for '\0'
17525 JSON_ASSERT(n_chars < number_buffer.size() - 1);
17526
17527 // jump to the end to generate the string from backward,
17528 // so we later avoid reversing the result
17529 buffer_ptr += n_chars;
17530
17531 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei
17532 // Alexandrescu See: https://www.youtube.com/watch?v=o4-CwDo2zpg
17533 while (abs_value >= 100) {
17534 const auto digits_index = static_cast<unsigned>((abs_value % 100));
17535 abs_value /= 100;
17536 *(--buffer_ptr) = digits_to_99[digits_index][1];
17537 *(--buffer_ptr) = digits_to_99[digits_index][0];
17538 }
17539
17540 if (abs_value >= 10) {
17541 const auto digits_index = static_cast<unsigned>(abs_value);
17542 *(--buffer_ptr) = digits_to_99[digits_index][1];
17543 *(--buffer_ptr) = digits_to_99[digits_index][0];
17544 } else {
17545 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
17546 }
17547
17548 o->write_characters(number_buffer.data(), n_chars);
17549 }
17550
17559 void dump_float(number_float_t x) {
17560 // NaN / inf
17561 if (!std::isfinite(x)) {
17562 o->write_characters("null", 4);
17563 return;
17564 }
17565
17566 // If number_float_t is an IEEE-754 single or double precision number,
17567 // use the Grisu2 algorithm to produce short numbers which are
17568 // guaranteed to round-trip, using strtof and strtod, resp.
17569 //
17570 // NB: The test below works if <long double> == <double>.
17571 static constexpr bool is_ieee_single_or_double =
17572 (std::numeric_limits<number_float_t>::is_iec559 &&
17573 std::numeric_limits<number_float_t>::digits == 24 &&
17574 std::numeric_limits<number_float_t>::max_exponent == 128) ||
17575 (std::numeric_limits<number_float_t>::is_iec559 &&
17576 std::numeric_limits<number_float_t>::digits == 53 &&
17577 std::numeric_limits<number_float_t>::max_exponent == 1024);
17578
17579 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
17580 }
17581
17582 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) {
17583 auto* begin = number_buffer.data();
17584 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
17585
17586 o->write_characters(begin, static_cast<size_t>(end - begin));
17587 }
17588
17589 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) {
17590 // get number of digits for a float -> text -> float round-trip
17591 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
17592
17593 // the actual conversion
17594 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
17595 std::ptrdiff_t len =
17596 (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
17597
17598 // negative value indicates an error
17599 JSON_ASSERT(len > 0);
17600 // check if buffer was large enough
17601 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
17602
17603 // erase thousands separator
17604 if (thousands_sep != '\0') {
17605 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto):
17606 // std::remove returns an iterator, see
17607 // https://github.com/nlohmann/json/issues/3081
17608 const auto end =
17609 std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
17610 std::fill(end, number_buffer.end(), '\0');
17611 JSON_ASSERT((end - number_buffer.begin()) <= len);
17612 len = (end - number_buffer.begin());
17613 }
17614
17615 // convert decimal point to '.'
17616 if (decimal_point != '\0' && decimal_point != '.') {
17617 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto):
17618 // std::find returns an iterator, see
17619 // https://github.com/nlohmann/json/issues/3081
17620 const auto dec_pos =
17621 std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
17622 if (dec_pos != number_buffer.end()) {
17623 *dec_pos = '.';
17624 }
17625 }
17626
17627 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
17628
17629 // determine if we need to append ".0"
17630 const bool value_is_int_like =
17631 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
17632 [](char c) { return c == '.' || c == 'e'; });
17633
17634 if (value_is_int_like) {
17635 o->write_characters(".0", 2);
17636 }
17637 }
17638
17660 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep,
17661 const std::uint8_t byte) noexcept {
17662 static const std::array<std::uint8_t, 400> utf8d =
17663 {
17664 {
17665 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17666 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
17668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17670 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
17671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17672 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17673 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
17674 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17675 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17676 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
17677 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17678 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9,
17679 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
17680 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
17681 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
17682 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
17683 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2,
17684 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
17685 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
17686 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
17687 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
17688 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
17689 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
17690 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4,
17691 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
17692 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17693 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
17694 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
17695 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1,
17696 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17697 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
17698 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
17699 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17700 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
17701 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1,
17702 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1,
17703 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
17704 }};
17705
17706 JSON_ASSERT(byte < utf8d.size());
17707 const std::uint8_t type = utf8d[byte];
17708
17709 codep = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte);
17710
17711 const std::size_t index =
17712 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
17713 JSON_ASSERT(index < utf8d.size());
17714 state = utf8d[index];
17715 return state;
17716 }
17717
17718 /*
17719 * Overload to make the compiler happy while it is instantiating
17720 * dump_integer for number_unsigned_t.
17721 * Must never be called.
17722 */
17723 number_unsigned_t remove_sign(number_unsigned_t x) {
17724 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17725 // LCOV_EXCL_LINE
17726 return x; // LCOV_EXCL_LINE
17727 }
17728
17729 /*
17730 * Helper function for dump_integer
17731 *
17732 * This function takes a negative signed integer and returns its absolute
17733 * value as unsigned integer. The plus/minus shuffling is necessary as we can
17734 * not directly remove the sign of an arbitrary signed integer as the
17735 * absolute values of INT_MIN and INT_MAX are usually not the same. See
17736 * #1708 for details.
17737 */
17738 inline number_unsigned_t remove_sign(number_integer_t x) noexcept {
17739 JSON_ASSERT(x < 0 &&
17740 x < (std::numeric_limits<
17741 number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
17742 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
17743 }
17744
17745 private:
17747 output_adapter_t<char> o = nullptr;
17748
17750 std::array<char, 64> number_buffer{{}};
17751
17753 const std::lconv* loc = nullptr;
17755 const char thousands_sep = '\0';
17757 const char decimal_point = '\0';
17758
17760 std::array<char, 512> string_buffer{{}};
17761
17763 const char indent_char;
17766
17769};
17770
17771} // namespace detail
17772NLOHMANN_JSON_NAMESPACE_END
17773
17774// #include <nlohmann/detail/value_t.hpp>
17775
17776// #include <nlohmann/json_fwd.hpp>
17777
17778// #include <nlohmann/ordered_map.hpp>
17779// __ _____ _____ _____
17780// __| | __| | | | JSON for Modern C++
17781// | | |__ | | | | | | version 3.11.3
17782// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17783//
17784// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
17785// SPDX-License-Identifier: MIT
17786
17787#include <functional> // equal_to, less
17788#include <initializer_list> // initializer_list
17789#include <iterator> // input_iterator_tag, iterator_traits
17790#include <memory> // allocator
17791#include <stdexcept> // for out_of_range
17792#include <type_traits> // enable_if, is_convertible
17793#include <utility> // pair
17794#include <vector> // vector
17795
17796// #include <nlohmann/detail/macro_scope.hpp>
17797
17798// #include <nlohmann/detail/meta/type_traits.hpp>
17799
17800NLOHMANN_JSON_NAMESPACE_BEGIN
17801
17804template <class Key, class T, class IgnoredLess = std::less<Key>,
17805 class Allocator = std::allocator<std::pair<const Key, T>>>
17806struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> {
17807 using key_type = Key;
17808 using mapped_type = T;
17809 using Container = std::vector<std::pair<const Key, T>, Allocator>;
17810 using iterator = typename Container::iterator;
17811 using const_iterator = typename Container::const_iterator;
17812 using size_type = typename Container::size_type;
17813 using value_type = typename Container::value_type;
17814#ifdef JSON_HAS_CPP_14
17815 using key_compare = std::equal_to<>;
17816#else
17817 using key_compare = std::equal_to<Key>;
17818#endif
17819
17820 // Explicit constructors instead of `using Container::Container`
17821 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
17822 ordered_map() noexcept(noexcept(Container())) : Container{} {}
17823 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc)))
17824 : Container{alloc} {}
17825 template <class It>
17826 ordered_map(It first, It last, const Allocator& alloc = Allocator())
17827 : Container{first, last, alloc} {}
17828 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator())
17829 : Container{init, alloc} {}
17830
17831 std::pair<iterator, bool> emplace(const key_type& key, T&& t) {
17832 for (auto it = this->begin(); it != this->end(); ++it) {
17833 if (m_compare(it->first, key)) {
17834 return {it, false};
17835 }
17836 }
17837 Container::emplace_back(key, std::forward<T>(t));
17838 return {std::prev(this->end()), true};
17839 }
17840
17841 template <class KeyType,
17842 detail::enable_if_t<
17843 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
17844 std::pair<iterator, bool> emplace(KeyType&& key, T&& t) {
17845 for (auto it = this->begin(); it != this->end(); ++it) {
17846 if (m_compare(it->first, key)) {
17847 return {it, false};
17848 }
17849 }
17850 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
17851 return {std::prev(this->end()), true};
17852 }
17853
17854 T& operator[](const key_type& key) { return emplace(key, T{}).first->second; }
17855
17856 template <class KeyType,
17857 detail::enable_if_t<
17858 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
17859 T& operator[](KeyType&& key) {
17860 return emplace(std::forward<KeyType>(key), T{}).first->second;
17861 }
17862
17863 const T& operator[](const key_type& key) const { return at(key); }
17864
17865 template <class KeyType,
17866 detail::enable_if_t<
17867 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
17868 const T& operator[](KeyType&& key) const {
17869 return at(std::forward<KeyType>(key));
17870 }
17871
17872 T& at(const key_type& key) {
17873 for (auto it = this->begin(); it != this->end(); ++it) {
17874 if (m_compare(it->first, key)) {
17875 return it->second;
17876 }
17877 }
17878
17879 JSON_THROW(std::out_of_range("key not found"));
17880 }
17881
17882 template <
17883 class KeyType,
17884 detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
17885 int> = 0>
17886 T& at(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
17887 {
17888 for (auto it = this->begin(); it != this->end(); ++it) {
17889 if (m_compare(it->first, key)) {
17890 return it->second;
17891 }
17892 }
17893
17894 JSON_THROW(std::out_of_range("key not found"));
17895 }
17896
17897 const T& at(const key_type& key) const {
17898 for (auto it = this->begin(); it != this->end(); ++it) {
17899 if (m_compare(it->first, key)) {
17900 return it->second;
17901 }
17902 }
17903
17904 JSON_THROW(std::out_of_range("key not found"));
17905 }
17906
17907 template <
17908 class KeyType,
17909 detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
17910 int> = 0>
17911 const T& at(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
17912 {
17913 for (auto it = this->begin(); it != this->end(); ++it) {
17914 if (m_compare(it->first, key)) {
17915 return it->second;
17916 }
17917 }
17918
17919 JSON_THROW(std::out_of_range("key not found"));
17920 }
17921
17922 size_type erase(const key_type& key) {
17923 for (auto it = this->begin(); it != this->end(); ++it) {
17924 if (m_compare(it->first, key)) {
17925 // Since we cannot move const Keys, re-construct them in place
17926 for (auto next = it; ++next != this->end(); ++it) {
17927 it->~value_type(); // Destroy but keep allocation
17928 new (&*it) value_type{std::move(*next)};
17929 }
17930 Container::pop_back();
17931 return 1;
17932 }
17933 }
17934 return 0;
17935 }
17936
17937 template <
17938 class KeyType,
17939 detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
17940 int> = 0>
17941 size_type erase(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
17942 {
17943 for (auto it = this->begin(); it != this->end(); ++it) {
17944 if (m_compare(it->first, key)) {
17945 // Since we cannot move const Keys, re-construct them in place
17946 for (auto next = it; ++next != this->end(); ++it) {
17947 it->~value_type(); // Destroy but keep allocation
17948 new (&*it) value_type{std::move(*next)};
17949 }
17950 Container::pop_back();
17951 return 1;
17952 }
17953 }
17954 return 0;
17955 }
17956
17957 iterator erase(iterator pos) { return erase(pos, std::next(pos)); }
17958
17959 iterator erase(iterator first, iterator last) {
17960 if (first == last) {
17961 return first;
17962 }
17963
17964 const auto elements_affected = std::distance(first, last);
17965 const auto offset = std::distance(Container::begin(), first);
17966
17967 // This is the start situation. We need to delete elements_affected
17968 // elements (3 in this example: e, f, g), and need to return an
17969 // iterator past the last deleted element (h in this example).
17970 // Note that offset is the distance from the start of the vector
17971 // to first. We will need this later.
17972
17973 // [ a, b, c, d, e, f, g, h, i, j ]
17974 // ^ ^
17975 // first last
17976
17977 // Since we cannot move const Keys, we re-construct them in place.
17978 // We start at first and re-construct (viz. copy) the elements from
17979 // the back of the vector. Example for first iteration:
17980
17981 // ,--------.
17982 // v | destroy e and re-construct with h
17983 // [ a, b, c, d, e, f, g, h, i, j ]
17984 // ^ ^
17985 // it it + elements_affected
17986
17987 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) {
17988 it->~value_type(); // destroy but keep allocation
17989 new (&*it) value_type{
17990 std::move(*std::next(it, elements_affected))}; // "move" next element to it
17991 }
17992
17993 // [ a, b, c, d, h, i, j, h, i, j ]
17994 // ^ ^
17995 // first last
17996
17997 // remove the unneeded elements at the end of the vector
17998 Container::resize(this->size() - static_cast<size_type>(elements_affected));
17999
18000 // [ a, b, c, d, h, i, j ]
18001 // ^ ^
18002 // first last
18003
18004 // first is now pointing past the last deleted element, but we cannot
18005 // use this iterator, because it may have been invalidated by the
18006 // resize call. Instead, we can return begin() + offset.
18007 return Container::begin() + offset;
18008 }
18009
18010 size_type count(const key_type& key) const {
18011 for (auto it = this->begin(); it != this->end(); ++it) {
18012 if (m_compare(it->first, key)) {
18013 return 1;
18014 }
18015 }
18016 return 0;
18017 }
18018
18019 template <
18020 class KeyType,
18021 detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
18022 int> = 0>
18023 size_type count(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
18024 {
18025 for (auto it = this->begin(); it != this->end(); ++it) {
18026 if (m_compare(it->first, key)) {
18027 return 1;
18028 }
18029 }
18030 return 0;
18031 }
18032
18033 iterator find(const key_type& key) {
18034 for (auto it = this->begin(); it != this->end(); ++it) {
18035 if (m_compare(it->first, key)) {
18036 return it;
18037 }
18038 }
18039 return Container::end();
18040 }
18041
18042 template <
18043 class KeyType,
18044 detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
18045 int> = 0>
18046 iterator find(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
18047 {
18048 for (auto it = this->begin(); it != this->end(); ++it) {
18049 if (m_compare(it->first, key)) {
18050 return it;
18051 }
18052 }
18053 return Container::end();
18054 }
18055
18056 const_iterator find(const key_type& key) const {
18057 for (auto it = this->begin(); it != this->end(); ++it) {
18058 if (m_compare(it->first, key)) {
18059 return it;
18060 }
18061 }
18062 return Container::end();
18063 }
18064
18065 std::pair<iterator, bool> insert(value_type&& value) {
18066 return emplace(value.first, std::move(value.second));
18067 }
18068
18069 std::pair<iterator, bool> insert(const value_type& value) {
18070 for (auto it = this->begin(); it != this->end(); ++it) {
18071 if (m_compare(it->first, value.first)) {
18072 return {it, false};
18073 }
18074 }
18075 Container::push_back(value);
18076 return {--this->end(), true};
18077 }
18078
18079 template <typename InputIt>
18080 using require_input_iter = typename std::enable_if<
18081 std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
18082 std::input_iterator_tag>::value>::type;
18083
18084 template <typename InputIt, typename = require_input_iter<InputIt>>
18085 void insert(InputIt first, InputIt last) {
18086 for (auto it = first; it != last; ++it) {
18087 insert(*it);
18088 }
18089 }
18090
18091 private:
18092 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
18093};
18094
18095NLOHMANN_JSON_NAMESPACE_END
18096
18097#if defined(JSON_HAS_CPP_17)
18098#if JSON_HAS_STATIC_RTTI
18099#include <any>
18100#endif
18101#include <string_view>
18102#endif
18103
18109NLOHMANN_JSON_NAMESPACE_BEGIN
18110
18129NLOHMANN_BASIC_JSON_TPL_DECLARATION
18130class
18131 basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
18132 : public ::nlohmann::detail::json_base_class<CustomBaseClass> {
18133 private:
18134 template <detail::value_t> friend struct detail::external_constructor;
18135
18136 template <typename> friend class ::nlohmann::json_pointer;
18137 // can be restored when json_pointer backwards compatibility is removed
18138 // friend ::nlohmann::json_pointer<StringType>;
18139
18140 template <typename BasicJsonType, typename InputType> friend class ::nlohmann::detail::parser;
18141 friend ::nlohmann::detail::serializer<basic_json>;
18142 template <typename BasicJsonType> friend class ::nlohmann::detail::iter_impl;
18143 template <typename BasicJsonType, typename CharType>
18144 friend class ::nlohmann::detail::binary_writer;
18145 template <typename BasicJsonType, typename InputType, typename SAX>
18146 friend class ::nlohmann::detail::binary_reader;
18147 template <typename BasicJsonType> friend class ::nlohmann::detail::json_sax_dom_parser;
18148 template <typename BasicJsonType> friend class ::nlohmann::detail::json_sax_dom_callback_parser;
18149 friend class ::nlohmann::detail::exception;
18150
18152 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
18153 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
18154
18155 JSON_PRIVATE_UNLESS_TESTED :
18156 // convenience aliases for types residing in namespace detail;
18157 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
18158
18159 template <typename InputAdapterType>
18160 static ::nlohmann::detail::parser<basic_json, InputAdapterType>
18161 parser(InputAdapterType adapter, detail::parser_callback_t<basic_json> cb = nullptr,
18162 const bool allow_exceptions = true, const bool ignore_comments = false) {
18163 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(
18164 std::move(adapter), std::move(cb), allow_exceptions, ignore_comments);
18165 }
18166
18167 private:
18168 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
18169 template <typename BasicJsonType>
18170 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
18171 template <typename BasicJsonType>
18172 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
18173 template <typename Iterator>
18174 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
18175 template <typename Base>
18176 using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
18177
18178 template <typename CharType>
18179 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
18180
18181 template <typename InputType>
18182 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
18183 template <typename CharType>
18184 using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
18185
18186 JSON_PRIVATE_UNLESS_TESTED : using serializer = ::nlohmann::detail::serializer<basic_json>;
18187
18188 public:
18189 using value_t = detail::value_t;
18191 using json_pointer = ::nlohmann::json_pointer<StringType>;
18192 template <typename T, typename SFINAE> using json_serializer = JSONSerializer<T, SFINAE>;
18198 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
18199
18200 using input_format_t = detail::input_format_t;
18203
18205 // exceptions //
18207
18211
18212 using exception = detail::exception;
18213 using parse_error = detail::parse_error;
18214 using invalid_iterator = detail::invalid_iterator;
18215 using type_error = detail::type_error;
18216 using out_of_range = detail::out_of_range;
18217 using other_error = detail::other_error;
18218
18220
18222 // container types //
18224
18229
18232
18237
18239 using difference_type = std::ptrdiff_t;
18241 using size_type = std::size_t;
18242
18244 using allocator_type = AllocatorType<basic_json>;
18245
18247 using pointer = typename std::allocator_traits<allocator_type>::pointer;
18249 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
18250
18252 using iterator = iter_impl<basic_json>;
18254 using const_iterator = iter_impl<const basic_json>;
18256 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
18258 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
18259
18261
18265
18268 JSON_HEDLEY_WARN_UNUSED_RESULT
18269 static basic_json meta() {
18270 basic_json result;
18271
18272 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
18273 result["name"] = "JSON for Modern C++";
18274 result["url"] = "https://github.com/nlohmann/json";
18275 result["version"]["string"] =
18276 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
18277 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
18278 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
18279 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
18280 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
18281 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
18282
18283#ifdef _WIN32
18284 result["platform"] = "win32";
18285#elif defined __linux__
18286 result["platform"] = "linux";
18287#elif defined __APPLE__
18288 result["platform"] = "apple";
18289#elif defined __unix__
18290 result["platform"] = "unix";
18291#else
18292 result["platform"] = "unknown";
18293#endif
18294
18295#if defined(__ICC) || defined(__INTEL_COMPILER)
18296 result["compiler"] = {{"family", "icc"}, { "version", __INTEL_COMPILER }};
18297#elif defined(__clang__)
18298 result["compiler"] = {{"family", "clang"}, { "version", __clang_version__ }};
18299#elif defined(__GNUC__) || defined(__GNUG__)
18300 result["compiler"] = {
18301 {"family", "gcc"},
18302 { "version",
18303 detail::concat(std::to_string(__GNUC__), '.', std::to_string(__GNUC_MINOR__), '.',
18304 std::to_string(__GNUC_PATCHLEVEL__)) }};
18305#elif defined(__HP_cc) || defined(__HP_aCC)
18306 result["compiler"] = "hp"
18307#elif defined(__IBMCPP__)
18308 result["compiler"] = {{"family", "ilecpp"}, { "version", __IBMCPP__ }};
18309#elif defined(_MSC_VER)
18310 result["compiler"] = {{"family", "msvc"}, { "version", _MSC_VER }};
18311#elif defined(__PGI)
18312 result["compiler"] = {{"family", "pgcpp"}, { "version", __PGI }};
18313#elif defined(__SUNPRO_CC)
18314 result["compiler"] = {{"family", "sunpro"}, { "version", __SUNPRO_CC }};
18315#else
18316 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
18317#endif
18318
18319#if defined(_MSVC_LANG)
18320 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
18321#elif defined(__cplusplus)
18322 result["compiler"]["c++"] = std::to_string(__cplusplus);
18323#else
18324 result["compiler"]["c++"] = "unknown";
18325#endif
18326 return result;
18327 }
18328
18330 // JSON value data types //
18332
18337
18342#if defined(JSON_HAS_CPP_14)
18343 // use of transparent comparator avoids unnecessary repeated construction of
18344 // temporaries in functions involving lookup by key with types other than
18345 // object_t::key_type (aka. StringType)
18346 using default_object_comparator_t = std::less<>;
18347#else
18348 using default_object_comparator_t = std::less<StringType>;
18349#endif
18350
18353 using object_t = ObjectType<StringType, basic_json, default_object_comparator_t,
18354 AllocatorType<std::pair<const StringType, basic_json>>>;
18355
18358 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
18359
18362 using string_t = StringType;
18363
18366 using boolean_t = BooleanType;
18367
18370 using number_integer_t = NumberIntegerType;
18371
18374 using number_unsigned_t = NumberUnsignedType;
18375
18378 using number_float_t = NumberFloatType;
18379
18382 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
18383
18386 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
18387
18389
18390 private:
18392 template <typename T, typename... Args>
18393 JSON_HEDLEY_RETURNS_NON_NULL static T* create(Args&&... args) {
18394 AllocatorType<T> alloc;
18395 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
18396
18397 auto deleter = [&](T* obj) { AllocatorTraits::deallocate(alloc, obj, 1); };
18398 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
18399 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
18400 JSON_ASSERT(obj != nullptr);
18401 return obj.release();
18402 }
18403
18405 // JSON value storage //
18407
18408 JSON_PRIVATE_UNLESS_TESTED :
18434 union json_value {
18436 object_t* object;
18438 array_t* array;
18440 string_t* string;
18442 binary_t* binary;
18444 boolean_t boolean;
18446 number_integer_t number_integer;
18448 number_unsigned_t number_unsigned;
18450 number_float_t number_float;
18451
18453 json_value() = default;
18455 json_value(boolean_t v) noexcept : boolean(v) {}
18457 json_value(number_integer_t v) noexcept : number_integer(v) {}
18459 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
18461 json_value(number_float_t v) noexcept : number_float(v) {}
18463 json_value(value_t t) {
18464 switch (t) {
18465 case value_t::object: {
18466 object = create<object_t>();
18467 break;
18468 }
18469
18470 case value_t::array: {
18471 array = create<array_t>();
18472 break;
18473 }
18474
18475 case value_t::string: {
18476 string = create<string_t>("");
18477 break;
18478 }
18479
18480 case value_t::binary: {
18481 binary = create<binary_t>();
18482 break;
18483 }
18484
18485 case value_t::boolean: {
18486 boolean = static_cast<boolean_t>(false);
18487 break;
18488 }
18489
18490 case value_t::number_integer: {
18491 number_integer = static_cast<number_integer_t>(0);
18492 break;
18493 }
18494
18495 case value_t::number_unsigned: {
18496 number_unsigned = static_cast<number_unsigned_t>(0);
18497 break;
18498 }
18499
18500 case value_t::number_float: {
18501 number_float = static_cast<number_float_t>(0.0);
18502 break;
18503 }
18504
18505 case value_t::null: {
18506 object = nullptr; // silence warning, see #821
18507 break;
18508 }
18509
18510 case value_t::discarded:
18511 default: {
18512 object = nullptr; // silence warning, see #821
18513 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) {
18514 JSON_THROW(other_error::create(
18515 500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3",
18516 nullptr)); // LCOV_EXCL_LINE
18517 }
18518 break;
18519 }
18520 }
18521 }
18522
18524 json_value(const string_t& value) : string(create<string_t>(value)) {}
18525
18527 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
18528
18530 json_value(const object_t& value) : object(create<object_t>(value)) {}
18531
18533 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
18534
18536 json_value(const array_t& value) : array(create<array_t>(value)) {}
18537
18539 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
18540
18542 json_value(const typename binary_t::container_type& value)
18543 : binary(create<binary_t>(value)) {}
18544
18546 json_value(typename binary_t::container_type&& value)
18547 : binary(create<binary_t>(std::move(value))) {}
18548
18550 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
18551
18553 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
18554
18555 void destroy(value_t t) {
18556 if ((t == value_t::object && object == nullptr) ||
18557 (t == value_t::array && array == nullptr) ||
18558 (t == value_t::string && string == nullptr) ||
18559 (t == value_t::binary && binary == nullptr)) {
18560 // not initialized (e.g. due to exception in the ctor)
18561 return;
18562 }
18563 if (t == value_t::array || t == value_t::object) {
18564 // flatten the current json_value to a heap-allocated stack
18565 std::vector<basic_json> stack;
18566
18567 // move the top-level items to stack
18568 if (t == value_t::array) {
18569 stack.reserve(array->size());
18570 std::move(array->begin(), array->end(), std::back_inserter(stack));
18571 } else {
18572 stack.reserve(object->size());
18573 for (auto&& it : *object) {
18574 stack.push_back(std::move(it.second));
18575 }
18576 }
18577
18578 while (!stack.empty()) {
18579 // move the last item to local variable to be processed
18580 basic_json current_item(std::move(stack.back()));
18581 stack.pop_back();
18582
18583 // if current_item is array/object, move
18584 // its children to the stack to be processed later
18585 if (current_item.is_array()) {
18586 std::move(current_item.m_data.m_value.array->begin(),
18587 current_item.m_data.m_value.array->end(),
18588 std::back_inserter(stack));
18589
18590 current_item.m_data.m_value.array->clear();
18591 } else if (current_item.is_object()) {
18592 for (auto&& it : *current_item.m_data.m_value.object) {
18593 stack.push_back(std::move(it.second));
18594 }
18595
18596 current_item.m_data.m_value.object->clear();
18597 }
18598
18599 // it's now safe that current_item get destructed
18600 // since it doesn't have any children
18601 }
18602 }
18603
18604 switch (t) {
18605 case value_t::object: {
18606 AllocatorType<object_t> alloc;
18607 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
18608 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
18609 break;
18610 }
18611
18612 case value_t::array: {
18613 AllocatorType<array_t> alloc;
18614 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
18615 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
18616 break;
18617 }
18618
18619 case value_t::string: {
18620 AllocatorType<string_t> alloc;
18621 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
18622 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
18623 break;
18624 }
18625
18626 case value_t::binary: {
18627 AllocatorType<binary_t> alloc;
18628 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
18629 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
18630 break;
18631 }
18632
18633 case value_t::null:
18634 case value_t::boolean:
18635 case value_t::number_integer:
18636 case value_t::number_unsigned:
18637 case value_t::number_float:
18638 case value_t::discarded:
18639 default: {
18640 break;
18641 }
18642 }
18643 }
18644 };
18645
18646 private:
18665 void assert_invariant(bool check_parents = true) const noexcept {
18666 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
18667 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
18668 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
18669 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
18670
18671#if JSON_DIAGNOSTICS
18672 JSON_TRY {
18673 // cppcheck-suppress assertWithSideEffect
18674 JSON_ASSERT(!check_parents || !is_structured() ||
18675 std::all_of(begin(), end(),
18676 [this](const basic_json& j) { return j.m_parent == this; }));
18677 }
18678 JSON_CATCH(...) {} // LCOV_EXCL_LINE
18679#endif
18680 static_cast<void>(check_parents);
18681 }
18682
18683 void set_parents() {
18684#if JSON_DIAGNOSTICS
18685 switch (m_data.m_type) {
18686 case value_t::array: {
18687 for (auto& element : *m_data.m_value.array) {
18688 element.m_parent = this;
18689 }
18690 break;
18691 }
18692
18693 case value_t::object: {
18694 for (auto& element : *m_data.m_value.object) {
18695 element.second.m_parent = this;
18696 }
18697 break;
18698 }
18699
18700 case value_t::null:
18701 case value_t::string:
18702 case value_t::boolean:
18703 case value_t::number_integer:
18704 case value_t::number_unsigned:
18705 case value_t::number_float:
18706 case value_t::binary:
18707 case value_t::discarded:
18708 default:
18709 break;
18710 }
18711#endif
18712 }
18713
18714 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) {
18715#if JSON_DIAGNOSTICS
18716 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) {
18717 (it + i)->m_parent = this;
18718 }
18719#else
18720 static_cast<void>(count_set_parents);
18721#endif
18722 return it;
18723 }
18724
18725 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) {
18726#if JSON_DIAGNOSTICS
18727 if (old_capacity != static_cast<std::size_t>(-1)) {
18728 // see https://github.com/nlohmann/json/issues/2838
18729 JSON_ASSERT(type() == value_t::array);
18730 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
18731 // capacity has changed: update all parents
18732 set_parents();
18733 return j;
18734 }
18735 }
18736
18737 // ordered_json uses a vector internally, so pointers could have
18738 // been invalidated; see https://github.com/nlohmann/json/issues/2962
18739#ifdef JSON_HEDLEY_MSVC_VERSION
18740#pragma warning(push)
18741#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
18742#endif
18743 if (detail::is_ordered_map<object_t>::value) {
18744 set_parents();
18745 return j;
18746 }
18747#ifdef JSON_HEDLEY_MSVC_VERSION
18748#pragma warning(pop)
18749#endif
18750
18751 j.m_parent = this;
18752#else
18753 static_cast<void>(j);
18754 static_cast<void>(old_capacity);
18755#endif
18756 return j;
18757 }
18758
18759 public:
18761 // JSON parser callback //
18763
18767
18770 using parser_callback_t = detail::parser_callback_t<basic_json>;
18771
18773 // constructors //
18775
18780
18783 basic_json(const value_t v) : m_data(v) { assert_invariant(); }
18784
18787 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
18788 : basic_json(value_t::null) {
18789 assert_invariant();
18790 }
18791
18794 template <typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>,
18795 detail::enable_if_t<!detail::is_basic_json<U>::value &&
18796 detail::is_compatible_type<basic_json_t, U>::value,
18797 int> = 0>
18798 basic_json(CompatibleType&& val) noexcept(
18799 noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
18800 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
18801 std::forward<CompatibleType>(val)))) {
18802 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
18803 set_parents();
18804 assert_invariant();
18805 }
18806
18809 template <typename BasicJsonType,
18810 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value &&
18811 !std::is_same<basic_json, BasicJsonType>::value,
18812 int> = 0>
18813 basic_json(const BasicJsonType& val) {
18814 using other_boolean_t = typename BasicJsonType::boolean_t;
18815 using other_number_float_t = typename BasicJsonType::number_float_t;
18816 using other_number_integer_t = typename BasicJsonType::number_integer_t;
18817 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18818 using other_string_t = typename BasicJsonType::string_t;
18819 using other_object_t = typename BasicJsonType::object_t;
18820 using other_array_t = typename BasicJsonType::array_t;
18821 using other_binary_t = typename BasicJsonType::binary_t;
18822
18823 switch (val.type()) {
18824 case value_t::boolean:
18825 JSONSerializer<other_boolean_t>::to_json(*this,
18826 val.template get<other_boolean_t>());
18827 break;
18828 case value_t::number_float:
18829 JSONSerializer<other_number_float_t>::to_json(
18830 *this, val.template get<other_number_float_t>());
18831 break;
18832 case value_t::number_integer:
18833 JSONSerializer<other_number_integer_t>::to_json(
18834 *this, val.template get<other_number_integer_t>());
18835 break;
18836 case value_t::number_unsigned:
18837 JSONSerializer<other_number_unsigned_t>::to_json(
18838 *this, val.template get<other_number_unsigned_t>());
18839 break;
18840 case value_t::string:
18841 JSONSerializer<other_string_t>::to_json(
18842 *this, val.template get_ref<const other_string_t&>());
18843 break;
18844 case value_t::object:
18845 JSONSerializer<other_object_t>::to_json(
18846 *this, val.template get_ref<const other_object_t&>());
18847 break;
18848 case value_t::array:
18849 JSONSerializer<other_array_t>::to_json(
18850 *this, val.template get_ref<const other_array_t&>());
18851 break;
18852 case value_t::binary:
18853 JSONSerializer<other_binary_t>::to_json(
18854 *this, val.template get_ref<const other_binary_t&>());
18855 break;
18856 case value_t::null:
18857 *this = nullptr;
18858 break;
18859 case value_t::discarded:
18860 m_data.m_type = value_t::discarded;
18861 break;
18862 default: // LCOV_EXCL_LINE
18863 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
18864 // LCOV_EXCL_LINE
18865 }
18866 JSON_ASSERT(m_data.m_type == val.type());
18867 set_parents();
18868 assert_invariant();
18869 }
18870
18873 basic_json(initializer_list_t init, bool type_deduction = true,
18874 value_t manual_type = value_t::array) {
18875 // check if each element is an array with two elements whose first
18876 // element is a string
18877 bool is_an_object = std::all_of(
18878 init.begin(), init.end(), [](const detail::json_ref<basic_json>& element_ref) {
18879 // The cast is to ensure op[size_type] is called, bearing in mind
18880 // size_type may not be int; (many string types can be constructed
18881 // from 0 via its null-pointer guise, so we get a broken call to
18882 // op[key_type], the wrong semantics and a 4804 warning on Windows)
18883 return element_ref->is_array() && element_ref->size() == 2 &&
18884 (*element_ref)[static_cast<size_type>(0)].is_string();
18885 });
18886
18887 // adjust type if type deduction is not wanted
18888 if (!type_deduction) {
18889 // if array is wanted, do not create an object though possible
18890 if (manual_type == value_t::array) {
18891 is_an_object = false;
18892 }
18893
18894 // if object is wanted but impossible, throw an exception
18895 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) {
18896 JSON_THROW(
18897 type_error::create(301, "cannot create object from initializer list", nullptr));
18898 }
18899 }
18900
18901 if (is_an_object) {
18902 // the initializer list is a list of pairs -> create object
18903 m_data.m_type = value_t::object;
18904 m_data.m_value = value_t::object;
18905
18906 for (auto& element_ref : init) {
18907 auto element = element_ref.moved_or_copied();
18908 m_data.m_value.object->emplace(
18909 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
18910 std::move((*element.m_data.m_value.array)[1]));
18911 }
18912 } else {
18913 // the initializer list describes an array -> create array
18914 m_data.m_type = value_t::array;
18915 m_data.m_value.array = create<array_t>(init.begin(), init.end());
18916 }
18917
18918 set_parents();
18919 assert_invariant();
18920 }
18921
18924 JSON_HEDLEY_WARN_UNUSED_RESULT
18925 static basic_json binary(const typename binary_t::container_type& init) {
18926 auto res = basic_json();
18927 res.m_data.m_type = value_t::binary;
18928 res.m_data.m_value = init;
18929 return res;
18930 }
18931
18934 JSON_HEDLEY_WARN_UNUSED_RESULT
18935 static basic_json binary(const typename binary_t::container_type& init,
18936 typename binary_t::subtype_type subtype) {
18937 auto res = basic_json();
18938 res.m_data.m_type = value_t::binary;
18939 res.m_data.m_value = binary_t(init, subtype);
18940 return res;
18941 }
18942
18945 JSON_HEDLEY_WARN_UNUSED_RESULT
18946 static basic_json binary(typename binary_t::container_type&& init) {
18947 auto res = basic_json();
18948 res.m_data.m_type = value_t::binary;
18949 res.m_data.m_value = std::move(init);
18950 return res;
18951 }
18952
18955 JSON_HEDLEY_WARN_UNUSED_RESULT
18956 static basic_json binary(typename binary_t::container_type&& init,
18957 typename binary_t::subtype_type subtype) {
18958 auto res = basic_json();
18959 res.m_data.m_type = value_t::binary;
18960 res.m_data.m_value = binary_t(std::move(init), subtype);
18961 return res;
18962 }
18963
18966 JSON_HEDLEY_WARN_UNUSED_RESULT
18968 return basic_json(init, false, value_t::array);
18969 }
18970
18973 JSON_HEDLEY_WARN_UNUSED_RESULT
18975 return basic_json(init, false, value_t::object);
18976 }
18977
18980 basic_json(size_type cnt, const basic_json& val) : m_data{cnt, val} {
18981 set_parents();
18982 assert_invariant();
18983 }
18984
18987 template <class InputIT,
18988 typename std::enable_if<
18989 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
18990 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
18991 int>::type = 0>
18992 basic_json(InputIT first, InputIT last) {
18993 JSON_ASSERT(first.m_object != nullptr);
18994 JSON_ASSERT(last.m_object != nullptr);
18995
18996 // make sure iterator fits the current value
18997 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
18998 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
18999 }
19000
19001 // copy type from first iterator
19002 m_data.m_type = first.m_object->m_data.m_type;
19003
19004 // check if iterator range is complete for primitive values
19005 switch (m_data.m_type) {
19006 case value_t::boolean:
19007 case value_t::number_float:
19008 case value_t::number_integer:
19009 case value_t::number_unsigned:
19010 case value_t::string: {
19011 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() ||
19012 !last.m_it.primitive_iterator.is_end())) {
19013 JSON_THROW(
19014 invalid_iterator::create(204, "iterators out of range", first.m_object));
19015 }
19016 break;
19017 }
19018
19019 case value_t::null:
19020 case value_t::object:
19021 case value_t::array:
19022 case value_t::binary:
19023 case value_t::discarded:
19024 default:
19025 break;
19026 }
19027
19028 switch (m_data.m_type) {
19029 case value_t::number_integer: {
19030 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
19031 break;
19032 }
19033
19034 case value_t::number_unsigned: {
19035 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
19036 break;
19037 }
19038
19039 case value_t::number_float: {
19040 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
19041 break;
19042 }
19043
19044 case value_t::boolean: {
19045 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
19046 break;
19047 }
19048
19049 case value_t::string: {
19050 m_data.m_value = *first.m_object->m_data.m_value.string;
19051 break;
19052 }
19053
19054 case value_t::object: {
19055 m_data.m_value.object =
19056 create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
19057 break;
19058 }
19059
19060 case value_t::array: {
19061 m_data.m_value.array =
19062 create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
19063 break;
19064 }
19065
19066 case value_t::binary: {
19067 m_data.m_value = *first.m_object->m_data.m_value.binary;
19068 break;
19069 }
19070
19071 case value_t::null:
19072 case value_t::discarded:
19073 default:
19074 JSON_THROW(
19075 invalid_iterator::create(206,
19076 detail::concat("cannot construct with iterators from ",
19077 first.m_object->type_name()),
19078 first.m_object));
19079 }
19080
19081 set_parents();
19082 assert_invariant();
19083 }
19084
19086 // other constructors and destructor //
19088
19089 template <
19090 typename JsonRef,
19091 detail::enable_if_t<
19093 std::is_same<typename JsonRef::value_type, basic_json>>::value,
19094 int> = 0>
19095 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
19096
19099 basic_json(const basic_json& other) : json_base_class_t(other) {
19100 m_data.m_type = other.m_data.m_type;
19101 // check of passed value is valid
19102 other.assert_invariant();
19103
19104 switch (m_data.m_type) {
19105 case value_t::object: {
19106 m_data.m_value = *other.m_data.m_value.object;
19107 break;
19108 }
19109
19110 case value_t::array: {
19111 m_data.m_value = *other.m_data.m_value.array;
19112 break;
19113 }
19114
19115 case value_t::string: {
19116 m_data.m_value = *other.m_data.m_value.string;
19117 break;
19118 }
19119
19120 case value_t::boolean: {
19121 m_data.m_value = other.m_data.m_value.boolean;
19122 break;
19123 }
19124
19125 case value_t::number_integer: {
19126 m_data.m_value = other.m_data.m_value.number_integer;
19127 break;
19128 }
19129
19130 case value_t::number_unsigned: {
19131 m_data.m_value = other.m_data.m_value.number_unsigned;
19132 break;
19133 }
19134
19135 case value_t::number_float: {
19136 m_data.m_value = other.m_data.m_value.number_float;
19137 break;
19138 }
19139
19140 case value_t::binary: {
19141 m_data.m_value = *other.m_data.m_value.binary;
19142 break;
19143 }
19144
19145 case value_t::null:
19146 case value_t::discarded:
19147 default:
19148 break;
19149 }
19150
19151 set_parents();
19152 assert_invariant();
19153 }
19154
19157 basic_json(basic_json&& other) noexcept
19158 : json_base_class_t(std::forward<json_base_class_t>(other)),
19159 m_data(std::move(other.m_data)) {
19160 // check that passed value is valid
19161 other.assert_invariant(false);
19162
19163 // invalidate payload
19164 other.m_data.m_type = value_t::null;
19165 other.m_data.m_value = {};
19166
19167 set_parents();
19168 assert_invariant();
19169 }
19170
19174 std::is_nothrow_move_constructible<value_t>::value &&
19175 std::is_nothrow_move_assignable<value_t>::value &&
19176 std::is_nothrow_move_constructible<json_value>::value &&
19177 std::is_nothrow_move_assignable<json_value>::value &&
19178 std::is_nothrow_move_assignable<json_base_class_t>::value) {
19179 // check that passed value is valid
19180 other.assert_invariant();
19181
19182 using std::swap;
19183 swap(m_data.m_type, other.m_data.m_type);
19184 swap(m_data.m_value, other.m_data.m_value);
19185 json_base_class_t::operator=(std::move(other));
19186
19187 set_parents();
19188 assert_invariant();
19189 return *this;
19190 }
19191
19194 ~basic_json() noexcept { assert_invariant(false); }
19195
19197
19198 public:
19200 // object inspection //
19202
19206
19209 string_t dump(const int indent = -1, const char indent_char = ' ',
19210 const bool ensure_ascii = false,
19211 const error_handler_t error_handler = error_handler_t::strict) const {
19212 string_t result;
19213 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
19214
19215 if (indent >= 0) {
19216 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
19217 } else {
19218 s.dump(*this, false, ensure_ascii, 0);
19219 }
19220
19221 return result;
19222 }
19223
19226 constexpr value_t type() const noexcept { return m_data.m_type; }
19227
19230 constexpr bool is_primitive() const noexcept {
19231 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
19232 }
19233
19236 constexpr bool is_structured() const noexcept { return is_array() || is_object(); }
19237
19240 constexpr bool is_null() const noexcept { return m_data.m_type == value_t::null; }
19241
19244 constexpr bool is_boolean() const noexcept { return m_data.m_type == value_t::boolean; }
19245
19248 constexpr bool is_number() const noexcept { return is_number_integer() || is_number_float(); }
19249
19252 constexpr bool is_number_integer() const noexcept {
19253 return m_data.m_type == value_t::number_integer ||
19254 m_data.m_type == value_t::number_unsigned;
19255 }
19256
19259 constexpr bool is_number_unsigned() const noexcept {
19260 return m_data.m_type == value_t::number_unsigned;
19261 }
19262
19265 constexpr bool is_number_float() const noexcept {
19266 return m_data.m_type == value_t::number_float;
19267 }
19268
19271 constexpr bool is_object() const noexcept { return m_data.m_type == value_t::object; }
19272
19275 constexpr bool is_array() const noexcept { return m_data.m_type == value_t::array; }
19276
19279 constexpr bool is_string() const noexcept { return m_data.m_type == value_t::string; }
19280
19283 constexpr bool is_binary() const noexcept { return m_data.m_type == value_t::binary; }
19284
19287 constexpr bool is_discarded() const noexcept { return m_data.m_type == value_t::discarded; }
19288
19291 constexpr operator value_t() const noexcept { return m_data.m_type; }
19292
19294
19295 private:
19297 // value access //
19299
19301 boolean_t get_impl(boolean_t* /*unused*/) const {
19302 if (JSON_HEDLEY_LIKELY(is_boolean())) {
19303 return m_data.m_value.boolean;
19304 }
19305
19306 JSON_THROW(type_error::create(
19307 302, detail::concat("type must be boolean, but is ", type_name()), this));
19308 }
19309
19311 object_t* get_impl_ptr(object_t* /*unused*/) noexcept {
19312 return is_object() ? m_data.m_value.object : nullptr;
19313 }
19314
19316 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept {
19317 return is_object() ? m_data.m_value.object : nullptr;
19318 }
19319
19321 array_t* get_impl_ptr(array_t* /*unused*/) noexcept {
19322 return is_array() ? m_data.m_value.array : nullptr;
19323 }
19324
19326 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept {
19327 return is_array() ? m_data.m_value.array : nullptr;
19328 }
19329
19331 string_t* get_impl_ptr(string_t* /*unused*/) noexcept {
19332 return is_string() ? m_data.m_value.string : nullptr;
19333 }
19334
19336 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept {
19337 return is_string() ? m_data.m_value.string : nullptr;
19338 }
19339
19341 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept {
19342 return is_boolean() ? &m_data.m_value.boolean : nullptr;
19343 }
19344
19346 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept {
19347 return is_boolean() ? &m_data.m_value.boolean : nullptr;
19348 }
19349
19351 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept {
19352 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
19353 }
19354
19356 constexpr const number_integer_t*
19357 get_impl_ptr(const number_integer_t* /*unused*/) const noexcept {
19358 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
19359 }
19360
19362 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept {
19363 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
19364 }
19365
19367 constexpr const number_unsigned_t*
19368 get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept {
19369 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
19370 }
19371
19373 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept {
19374 return is_number_float() ? &m_data.m_value.number_float : nullptr;
19375 }
19376
19378 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept {
19379 return is_number_float() ? &m_data.m_value.number_float : nullptr;
19380 }
19381
19383 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept {
19384 return is_binary() ? m_data.m_value.binary : nullptr;
19385 }
19386
19388 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept {
19389 return is_binary() ? m_data.m_value.binary : nullptr;
19390 }
19391
19403 template <typename ReferenceType, typename ThisType>
19404 static ReferenceType get_ref_impl(ThisType& obj) {
19405 // delegate the call to get_ptr<>()
19406 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
19407
19408 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) {
19409 return *ptr;
19410 }
19411
19412 JSON_THROW(type_error::create(
19413 303,
19414 detail::concat("incompatible ReferenceType for get_ref, actual type is ",
19415 obj.type_name()),
19416 &obj));
19417 }
19418
19419 public:
19423
19426 template <typename PointerType,
19427 typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
19428 auto get_ptr() noexcept
19429 -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
19430 // delegate the call to get_impl_ptr<>()
19431 return get_impl_ptr(static_cast<PointerType>(nullptr));
19432 }
19433
19436 template <typename PointerType,
19437 typename std::enable_if<
19438 std::is_pointer<PointerType>::value &&
19439 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
19440 int>::type = 0>
19441 constexpr auto get_ptr() const noexcept
19442 -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
19443 // delegate the call to get_impl_ptr<>() const
19444 return get_impl_ptr(static_cast<PointerType>(nullptr));
19445 }
19446
19447 private:
19488 template <typename ValueType,
19489 detail::enable_if_t<detail::is_default_constructible<ValueType>::value &&
19491 int> = 0>
19492 ValueType get_impl(detail::priority_tag<0> /*unused*/) const
19493 noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(),
19494 std::declval<ValueType&>()))) {
19495 auto ret = ValueType();
19496 JSONSerializer<ValueType>::from_json(*this, ret);
19497 return ret;
19498 }
19499
19532 template <typename ValueType,
19533 detail::enable_if_t<detail::has_non_default_from_json<basic_json_t, ValueType>::value,
19534 int> = 0>
19535 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(
19536 noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) {
19537 return JSONSerializer<ValueType>::from_json(*this);
19538 }
19539
19555 template <typename BasicJsonType,
19556 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
19557 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const {
19558 return *this;
19559 }
19560
19575 template <typename BasicJsonType,
19576 detail::enable_if_t<std::is_same<BasicJsonType, basic_json_t>::value, int> = 0>
19577 basic_json get_impl(detail::priority_tag<3> /*unused*/) const {
19578 return *this;
19579 }
19580
19585 template <typename PointerType,
19586 detail::enable_if_t<std::is_pointer<PointerType>::value, int> = 0>
19587 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
19588 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) {
19589 // delegate the call to get_ptr
19590 return get_ptr<PointerType>();
19591 }
19592
19593 public:
19619 template <typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
19620#if defined(JSON_HAS_CPP_14)
19621 constexpr
19622#endif
19623 auto
19624 get() const
19625 noexcept(noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(
19626 detail::priority_tag<4>{})))
19627 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(
19629 // we cannot static_assert on ValueTypeCV being non-const, because
19630 // there is support for get<const basic_json_t>(), which is why we
19631 // still need the uncvref
19632 static_assert(!std::is_reference<ValueTypeCV>::value,
19633 "get() cannot be used with reference types, you might want "
19634 "to use get_ref()");
19635 return get_impl<ValueType>(detail::priority_tag<4>{});
19636 }
19637
19665 template <typename PointerType,
19666 typename std::enable_if<std::is_pointer<PointerType>::value, int>::type = 0>
19667 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) {
19668 // delegate the call to get_ptr
19669 return get_ptr<PointerType>();
19670 }
19671
19674 template <typename ValueType,
19675 detail::enable_if_t<!detail::is_basic_json<ValueType>::value &&
19677 int> = 0>
19678 ValueType& get_to(ValueType& v) const
19679 noexcept(noexcept(JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(),
19680 v))) {
19681 JSONSerializer<ValueType>::from_json(*this, v);
19682 return v;
19683 }
19684
19685 // specialization to allow calling get_to with a basic_json value
19686 // see https://github.com/nlohmann/json/issues/2175
19687 template <typename ValueType,
19688 detail::enable_if_t<detail::is_basic_json<ValueType>::value, int> = 0>
19689 ValueType& get_to(ValueType& v) const {
19690 v = *this;
19691 return v;
19692 }
19693
19694 template <
19695 typename T, std::size_t N,
19696 typename Array = T (&)
19697 [N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
19698 detail::enable_if_t<detail::has_from_json<basic_json_t, Array>::value,
19699 int> = 0>
19700 Array get_to(T (&v)[N])
19701 const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
19702 noexcept(noexcept(JSONSerializer<Array>::from_json(std::declval<const basic_json_t&>(),
19703 v))) {
19704 JSONSerializer<Array>::from_json(*this, v);
19705 return v;
19706 }
19707
19710 template <typename ReferenceType,
19711 typename std::enable_if<std::is_reference<ReferenceType>::value, int>::type = 0>
19712 ReferenceType get_ref() {
19713 // delegate call to get_ref_impl
19714 return get_ref_impl<ReferenceType>(*this);
19715 }
19716
19719 template <typename ReferenceType,
19720 typename std::enable_if<
19721 std::is_reference<ReferenceType>::value &&
19722 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
19723 int>::type = 0>
19724 ReferenceType get_ref() const {
19725 // delegate call to get_ref_impl
19726 return get_ref_impl<ReferenceType>(*this);
19727 }
19728
19758 template <typename ValueType,
19759 typename std::enable_if<
19766 detail::negation<std::is_same<
19767 ValueType, std::initializer_list<typename string_t::value_type>>>,
19768#if defined(JSON_HAS_CPP_17) && \
19769 (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
19771#endif
19772#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
19774#endif
19775 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&,
19776 ValueType>>::value,
19777 int>::type = 0>
19778 JSON_EXPLICIT operator ValueType() const {
19779 // delegate the call to get<>() const
19780 return get<ValueType>();
19781 }
19782
19786 if (!is_binary()) {
19787 JSON_THROW(type_error::create(
19788 302, detail::concat("type must be binary, but is ", type_name()), this));
19789 }
19790
19791 return *get_ptr<binary_t*>();
19792 }
19793
19796 const binary_t& get_binary() const {
19797 if (!is_binary()) {
19798 JSON_THROW(type_error::create(
19799 302, detail::concat("type must be binary, but is ", type_name()), this));
19800 }
19801
19802 return *get_ptr<const binary_t*>();
19803 }
19804
19806
19808 // element access //
19810
19814
19818 // at only works for arrays
19819 if (JSON_HEDLEY_LIKELY(is_array())) {
19820 JSON_TRY {
19821 return set_parent(m_data.m_value.array->at(idx));
19822 }
19823 JSON_CATCH(std::out_of_range&) {
19824 // create better exception explanation
19825 JSON_THROW(out_of_range::create(
19826 401, detail::concat("array index ", std::to_string(idx), " is out of range"),
19827 this));
19828 }
19829 } else {
19830 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19831 this));
19832 }
19833 }
19834
19838 // at only works for arrays
19839 if (JSON_HEDLEY_LIKELY(is_array())) {
19840 JSON_TRY {
19841 return m_data.m_value.array->at(idx);
19842 }
19843 JSON_CATCH(std::out_of_range&) {
19844 // create better exception explanation
19845 JSON_THROW(out_of_range::create(
19846 401, detail::concat("array index ", std::to_string(idx), " is out of range"),
19847 this));
19848 }
19849 } else {
19850 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19851 this));
19852 }
19853 }
19854
19857 reference at(const typename object_t::key_type& key) {
19858 // at only works for objects
19859 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
19860 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19861 this));
19862 }
19863
19864 auto it = m_data.m_value.object->find(key);
19865 if (it == m_data.m_value.object->end()) {
19866 JSON_THROW(
19867 out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
19868 }
19869 return set_parent(it->second);
19870 }
19871
19874 template <class KeyType,
19875 detail::enable_if_t<
19876 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
19877 reference at(KeyType&& key) {
19878 // at only works for objects
19879 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
19880 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19881 this));
19882 }
19883
19884 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
19885 if (it == m_data.m_value.object->end()) {
19886 JSON_THROW(out_of_range::create(
19887 403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"),
19888 this));
19889 }
19890 return set_parent(it->second);
19891 }
19892
19895 const_reference at(const typename object_t::key_type& key) const {
19896 // at only works for objects
19897 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
19898 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19899 this));
19900 }
19901
19902 auto it = m_data.m_value.object->find(key);
19903 if (it == m_data.m_value.object->end()) {
19904 JSON_THROW(
19905 out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
19906 }
19907 return it->second;
19908 }
19909
19912 template <class KeyType,
19913 detail::enable_if_t<
19914 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
19915 const_reference at(KeyType&& key) const {
19916 // at only works for objects
19917 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
19918 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()),
19919 this));
19920 }
19921
19922 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
19923 if (it == m_data.m_value.object->end()) {
19924 JSON_THROW(out_of_range::create(
19925 403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"),
19926 this));
19927 }
19928 return it->second;
19929 }
19930
19934 // implicitly convert null value to an empty array
19935 if (is_null()) {
19936 m_data.m_type = value_t::array;
19937 m_data.m_value.array = create<array_t>();
19938 assert_invariant();
19939 }
19940
19941 // operator[] only works for arrays
19942 if (JSON_HEDLEY_LIKELY(is_array())) {
19943 // fill up array with null values if given idx is outside range
19944 if (idx >= m_data.m_value.array->size()) {
19945#if JSON_DIAGNOSTICS
19946 // remember array size & capacity before resizing
19947 const auto old_size = m_data.m_value.array->size();
19948 const auto old_capacity = m_data.m_value.array->capacity();
19949#endif
19950 m_data.m_value.array->resize(idx + 1);
19951
19952#if JSON_DIAGNOSTICS
19953 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
19954 // capacity has changed: update all parents
19955 set_parents();
19956 } else {
19957 // set parent for values added above
19958 set_parents(
19959 begin() + static_cast<typename iterator::difference_type>(old_size),
19960 static_cast<typename iterator::difference_type>(idx + 1 - old_size));
19961 }
19962#endif
19963 assert_invariant();
19964 }
19965
19966 return m_data.m_value.array->operator[](idx);
19967 }
19968
19969 JSON_THROW(type_error::create(
19970 305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()),
19971 this));
19972 }
19973
19977 // const operator[] only works for arrays
19978 if (JSON_HEDLEY_LIKELY(is_array())) {
19979 return m_data.m_value.array->operator[](idx);
19980 }
19981
19982 JSON_THROW(type_error::create(
19983 305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()),
19984 this));
19985 }
19986
19989 reference operator[](typename object_t::key_type key) {
19990 // implicitly convert null value to an empty object
19991 if (is_null()) {
19992 m_data.m_type = value_t::object;
19993 m_data.m_value.object = create<object_t>();
19994 assert_invariant();
19995 }
19996
19997 // operator[] only works for objects
19998 if (JSON_HEDLEY_LIKELY(is_object())) {
19999 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
20000 return set_parent(result.first->second);
20001 }
20002
20003 JSON_THROW(type_error::create(
20004 305, detail::concat("cannot use operator[] with a string argument with ", type_name()),
20005 this));
20006 }
20007
20010 const_reference operator[](const typename object_t::key_type& key) const {
20011 // const operator[] only works for objects
20012 if (JSON_HEDLEY_LIKELY(is_object())) {
20013 auto it = m_data.m_value.object->find(key);
20014 JSON_ASSERT(it != m_data.m_value.object->end());
20015 return it->second;
20016 }
20017
20018 JSON_THROW(type_error::create(
20019 305, detail::concat("cannot use operator[] with a string argument with ", type_name()),
20020 this));
20021 }
20022
20023 // these two functions resolve a (const) char * ambiguity affecting Clang and
20024 // MSVC (they seemingly cannot be constrained to resolve the ambiguity)
20025 template <typename T> reference operator[](T* key) {
20026 return operator[](typename object_t::key_type(key));
20027 }
20028
20029 template <typename T> const_reference operator[](T* key) const {
20030 return operator[](typename object_t::key_type(key));
20031 }
20032
20035 template <class KeyType,
20036 detail::enable_if_t<
20037 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20039 // implicitly convert null value to an empty object
20040 if (is_null()) {
20041 m_data.m_type = value_t::object;
20042 m_data.m_value.object = create<object_t>();
20043 assert_invariant();
20044 }
20045
20046 // operator[] only works for objects
20047 if (JSON_HEDLEY_LIKELY(is_object())) {
20048 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
20049 return set_parent(result.first->second);
20050 }
20051
20052 JSON_THROW(type_error::create(
20053 305, detail::concat("cannot use operator[] with a string argument with ", type_name()),
20054 this));
20055 }
20056
20059 template <class KeyType,
20060 detail::enable_if_t<
20061 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20062 const_reference operator[](KeyType&& key) const {
20063 // const operator[] only works for objects
20064 if (JSON_HEDLEY_LIKELY(is_object())) {
20065 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20066 JSON_ASSERT(it != m_data.m_value.object->end());
20067 return it->second;
20068 }
20069
20070 JSON_THROW(type_error::create(
20071 305, detail::concat("cannot use operator[] with a string argument with ", type_name()),
20072 this));
20073 }
20074
20075 private:
20076 template <typename KeyType>
20077 using is_comparable_with_object_key =
20079
20080 template <typename ValueType>
20081 using value_return_type = std::conditional<detail::is_c_string_uncvref<ValueType>::value,
20082 string_t, typename std::decay<ValueType>::type>;
20083
20084 public:
20087 template <class ValueType,
20088 detail::enable_if_t<!detail::is_transparent<object_comparator_t>::value &&
20089 detail::is_getable<basic_json_t, ValueType>::value &&
20090 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20091 int> = 0>
20092 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const {
20093 // value only works for objects
20094 if (JSON_HEDLEY_LIKELY(is_object())) {
20095 // if key is found, return value and given default value otherwise
20096 const auto it = find(key);
20097 if (it != end()) {
20098 return it->template get<ValueType>();
20099 }
20100
20101 return default_value;
20102 }
20103
20104 JSON_THROW(
20105 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20106 }
20107
20110 template <class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20111 detail::enable_if_t<!detail::is_transparent<object_comparator_t>::value &&
20112 detail::is_getable<basic_json_t, ReturnType>::value &&
20113 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20114 int> = 0>
20115 ReturnType value(const typename object_t::key_type& key, ValueType&& default_value) const {
20116 // value only works for objects
20117 if (JSON_HEDLEY_LIKELY(is_object())) {
20118 // if key is found, return value and given default value otherwise
20119 const auto it = find(key);
20120 if (it != end()) {
20121 return it->template get<ReturnType>();
20122 }
20123
20124 return std::forward<ValueType>(default_value);
20125 }
20126
20127 JSON_THROW(
20128 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20129 }
20130
20133 template <class ValueType, class KeyType,
20134 detail::enable_if_t<detail::is_transparent<object_comparator_t>::value &&
20135 !detail::is_json_pointer<KeyType>::value &&
20136 is_comparable_with_object_key<KeyType>::value &&
20137 detail::is_getable<basic_json_t, ValueType>::value &&
20138 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20139 int> = 0>
20140 ValueType value(KeyType&& key, const ValueType& default_value) const {
20141 // value only works for objects
20142 if (JSON_HEDLEY_LIKELY(is_object())) {
20143 // if key is found, return value and given default value otherwise
20144 const auto it = find(std::forward<KeyType>(key));
20145 if (it != end()) {
20146 return it->template get<ValueType>();
20147 }
20148
20149 return default_value;
20150 }
20151
20152 JSON_THROW(
20153 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20154 }
20155
20158 template <class ValueType, class KeyType,
20159 class ReturnType = typename value_return_type<ValueType>::type,
20160 detail::enable_if_t<detail::is_transparent<object_comparator_t>::value &&
20161 !detail::is_json_pointer<KeyType>::value &&
20162 is_comparable_with_object_key<KeyType>::value &&
20163 detail::is_getable<basic_json_t, ReturnType>::value &&
20164 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20165 int> = 0>
20166 ReturnType value(KeyType&& key, ValueType&& default_value) const {
20167 // value only works for objects
20168 if (JSON_HEDLEY_LIKELY(is_object())) {
20169 // if key is found, return value and given default value otherwise
20170 const auto it = find(std::forward<KeyType>(key));
20171 if (it != end()) {
20172 return it->template get<ReturnType>();
20173 }
20174
20175 return std::forward<ValueType>(default_value);
20176 }
20177
20178 JSON_THROW(
20179 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20180 }
20181
20184 template <class ValueType,
20185 detail::enable_if_t<detail::is_getable<basic_json_t, ValueType>::value &&
20186 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20187 int> = 0>
20188 ValueType value(const json_pointer& ptr, const ValueType& default_value) const {
20189 // value only works for objects
20190 if (JSON_HEDLEY_LIKELY(is_object())) {
20191 // if pointer resolves a value, return it or use default value
20192 JSON_TRY {
20193 return ptr.get_checked(this).template get<ValueType>();
20194 }
20195 JSON_INTERNAL_CATCH(out_of_range&) {
20196 return default_value;
20197 }
20198 }
20199
20200 JSON_THROW(
20201 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20202 }
20203
20206 template <class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20207 detail::enable_if_t<detail::is_getable<basic_json_t, ReturnType>::value &&
20208 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20209 int> = 0>
20210 ReturnType value(const json_pointer& ptr, ValueType&& default_value) const {
20211 // value only works for objects
20212 if (JSON_HEDLEY_LIKELY(is_object())) {
20213 // if pointer resolves a value, return it or use default value
20214 JSON_TRY {
20215 return ptr.get_checked(this).template get<ReturnType>();
20216 }
20217 JSON_INTERNAL_CATCH(out_of_range&) {
20218 return std::forward<ValueType>(default_value);
20219 }
20220 }
20221
20222 JSON_THROW(
20223 type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
20224 }
20225
20226 template <class ValueType, class BasicJsonType,
20227 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value &&
20228 detail::is_getable<basic_json_t, ValueType>::value &&
20229 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20230 int> = 0>
20232 3.11.0, basic_json::json_pointer or
20233 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
20234 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr,
20235 const ValueType& default_value) const {
20236 return value(ptr.convert(), default_value);
20237 }
20238
20239 template <class ValueType, class BasicJsonType,
20240 class ReturnType = typename value_return_type<ValueType>::type,
20241 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value &&
20242 detail::is_getable<basic_json_t, ReturnType>::value &&
20243 !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
20244 int> = 0>
20245 JSON_HEDLEY_DEPRECATED_FOR(
20246 3.11.0, basic_json::json_pointer or
20247 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
20248 ReturnType
20249 value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType&& default_value) const {
20250 return value(ptr.convert(), std::forward<ValueType>(default_value));
20251 }
20252
20255 reference front() { return *begin(); }
20256
20259 const_reference front() const { return *cbegin(); }
20260
20264 auto tmp = end();
20265 --tmp;
20266 return *tmp;
20267 }
20268
20272 auto tmp = cend();
20273 --tmp;
20274 return *tmp;
20275 }
20276
20279 template <class IteratorType,
20280 detail::enable_if_t<
20281 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20282 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
20283 int> = 0>
20284 IteratorType erase(IteratorType pos) {
20285 // make sure iterator fits the current value
20286 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) {
20287 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
20288 }
20289
20290 IteratorType result = end();
20291
20292 switch (m_data.m_type) {
20293 case value_t::boolean:
20294 case value_t::number_float:
20295 case value_t::number_integer:
20296 case value_t::number_unsigned:
20297 case value_t::string:
20298 case value_t::binary: {
20299 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) {
20300 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
20301 }
20302
20303 if (is_string()) {
20304 AllocatorType<string_t> alloc;
20305 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
20306 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string,
20307 1);
20308 m_data.m_value.string = nullptr;
20309 } else if (is_binary()) {
20310 AllocatorType<binary_t> alloc;
20311 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
20312 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary,
20313 1);
20314 m_data.m_value.binary = nullptr;
20315 }
20316
20317 m_data.m_type = value_t::null;
20318 assert_invariant();
20319 break;
20320 }
20321
20322 case value_t::object: {
20323 result.m_it.object_iterator =
20324 m_data.m_value.object->erase(pos.m_it.object_iterator);
20325 break;
20326 }
20327
20328 case value_t::array: {
20329 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
20330 break;
20331 }
20332
20333 case value_t::null:
20334 case value_t::discarded:
20335 default:
20336 JSON_THROW(type_error::create(
20337 307, detail::concat("cannot use erase() with ", type_name()), this));
20338 }
20339
20340 return result;
20341 }
20342
20345 template <class IteratorType,
20346 detail::enable_if_t<
20347 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
20348 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
20349 int> = 0>
20350 IteratorType erase(IteratorType first, IteratorType last) {
20351 // make sure iterator fits the current value
20352 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) {
20353 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
20354 }
20355
20356 IteratorType result = end();
20357
20358 switch (m_data.m_type) {
20359 case value_t::boolean:
20360 case value_t::number_float:
20361 case value_t::number_integer:
20362 case value_t::number_unsigned:
20363 case value_t::string:
20364 case value_t::binary: {
20365 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() ||
20366 !last.m_it.primitive_iterator.is_end())) {
20367 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
20368 }
20369
20370 if (is_string()) {
20371 AllocatorType<string_t> alloc;
20372 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
20373 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string,
20374 1);
20375 m_data.m_value.string = nullptr;
20376 } else if (is_binary()) {
20377 AllocatorType<binary_t> alloc;
20378 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
20379 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary,
20380 1);
20381 m_data.m_value.binary = nullptr;
20382 }
20383
20384 m_data.m_type = value_t::null;
20385 assert_invariant();
20386 break;
20387 }
20388
20389 case value_t::object: {
20390 result.m_it.object_iterator = m_data.m_value.object->erase(
20391 first.m_it.object_iterator, last.m_it.object_iterator);
20392 break;
20393 }
20394
20395 case value_t::array: {
20396 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
20397 last.m_it.array_iterator);
20398 break;
20399 }
20400
20401 case value_t::null:
20402 case value_t::discarded:
20403 default:
20404 JSON_THROW(type_error::create(
20405 307, detail::concat("cannot use erase() with ", type_name()), this));
20406 }
20407
20408 return result;
20409 }
20410
20411 private:
20412 template <
20413 typename KeyType,
20414 detail::enable_if_t<detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int> = 0>
20415 size_type erase_internal(KeyType&& key) {
20416 // this erase only works for objects
20417 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20418 JSON_THROW(type_error::create(
20419 307, detail::concat("cannot use erase() with ", type_name()), this));
20420 }
20421
20422 return m_data.m_value.object->erase(std::forward<KeyType>(key));
20423 }
20424
20425 template <typename KeyType,
20426 detail::enable_if_t<!detail::has_erase_with_key_type<basic_json_t, KeyType>::value,
20427 int> = 0>
20428 size_type erase_internal(KeyType&& key) {
20429 // this erase only works for objects
20430 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20431 JSON_THROW(type_error::create(
20432 307, detail::concat("cannot use erase() with ", type_name()), this));
20433 }
20434
20435 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20436 if (it != m_data.m_value.object->end()) {
20437 m_data.m_value.object->erase(it);
20438 return 1;
20439 }
20440 return 0;
20441 }
20442
20443 public:
20446 size_type erase(const typename object_t::key_type& key) {
20447 // the indirection via erase_internal() is added to avoid making this
20448 // function a template and thus de-rank it during overload resolution
20449 return erase_internal(key);
20450 }
20451
20454 template <class KeyType,
20455 detail::enable_if_t<
20456 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20457 size_type erase(KeyType&& key) {
20458 return erase_internal(std::forward<KeyType>(key));
20459 }
20460
20463 void erase(const size_type idx) {
20464 // this erase only works for arrays
20465 if (JSON_HEDLEY_LIKELY(is_array())) {
20466 if (JSON_HEDLEY_UNLIKELY(idx >= size())) {
20467 JSON_THROW(out_of_range::create(
20468 401, detail::concat("array index ", std::to_string(idx), " is out of range"),
20469 this));
20470 }
20471
20472 m_data.m_value.array->erase(m_data.m_value.array->begin() +
20473 static_cast<difference_type>(idx));
20474 } else {
20475 JSON_THROW(type_error::create(
20476 307, detail::concat("cannot use erase() with ", type_name()), this));
20477 }
20478 }
20479
20481
20483 // lookup //
20485
20488
20491 iterator find(const typename object_t::key_type& key) {
20492 auto result = end();
20493
20494 if (is_object()) {
20495 result.m_it.object_iterator = m_data.m_value.object->find(key);
20496 }
20497
20498 return result;
20499 }
20500
20503 const_iterator find(const typename object_t::key_type& key) const {
20504 auto result = cend();
20505
20506 if (is_object()) {
20507 result.m_it.object_iterator = m_data.m_value.object->find(key);
20508 }
20509
20510 return result;
20511 }
20512
20515 template <class KeyType,
20516 detail::enable_if_t<
20517 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20518 iterator find(KeyType&& key) {
20519 auto result = end();
20520
20521 if (is_object()) {
20522 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
20523 }
20524
20525 return result;
20526 }
20527
20530 template <class KeyType,
20531 detail::enable_if_t<
20532 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20533 const_iterator find(KeyType&& key) const {
20534 auto result = cend();
20535
20536 if (is_object()) {
20537 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
20538 }
20539
20540 return result;
20541 }
20542
20545 size_type count(const typename object_t::key_type& key) const {
20546 // return 0 for all nonobject types
20547 return is_object() ? m_data.m_value.object->count(key) : 0;
20548 }
20549
20552 template <class KeyType,
20553 detail::enable_if_t<
20554 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20555 size_type count(KeyType&& key) const {
20556 // return 0 for all nonobject types
20557 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
20558 }
20559
20562 bool contains(const typename object_t::key_type& key) const {
20563 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
20564 }
20565
20568 template <class KeyType,
20569 detail::enable_if_t<
20570 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
20571 bool contains(KeyType&& key) const {
20572 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) !=
20573 m_data.m_value.object->end();
20574 }
20575
20579 bool contains(const json_pointer& ptr) const { return ptr.contains(this); }
20580
20581 template <typename BasicJsonType,
20582 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
20583 JSON_HEDLEY_DEPRECATED_FOR(
20584 3.11.0, basic_json::json_pointer or
20585 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
20586 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
20587 return ptr.contains(this);
20588 }
20589
20591
20593 // iterators //
20595
20598
20601 iterator begin() noexcept {
20602 iterator result(this);
20603 result.set_begin();
20604 return result;
20605 }
20606
20609 const_iterator begin() const noexcept { return cbegin(); }
20610
20613 const_iterator cbegin() const noexcept {
20614 const_iterator result(this);
20615 result.set_begin();
20616 return result;
20617 }
20618
20621 iterator end() noexcept {
20622 iterator result(this);
20623 result.set_end();
20624 return result;
20625 }
20626
20629 const_iterator end() const noexcept { return cend(); }
20630
20633 const_iterator cend() const noexcept {
20634 const_iterator result(this);
20635 result.set_end();
20636 return result;
20637 }
20638
20641 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
20642
20645 const_reverse_iterator rbegin() const noexcept { return crbegin(); }
20646
20649 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
20650
20653 const_reverse_iterator rend() const noexcept { return crend(); }
20654
20657 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
20658
20661 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
20662
20663 public:
20669 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
20670 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept {
20671 return ref.items();
20672 }
20673
20679 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
20680 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept {
20681 return ref.items();
20682 }
20683
20686 iteration_proxy<iterator> items() noexcept { return iteration_proxy<iterator>(*this); }
20687
20690 iteration_proxy<const_iterator> items() const noexcept {
20691 return iteration_proxy<const_iterator>(*this);
20692 }
20693
20695
20697 // capacity //
20699
20702
20705 bool empty() const noexcept {
20706 switch (m_data.m_type) {
20707 case value_t::null: {
20708 // null values are empty
20709 return true;
20710 }
20711
20712 case value_t::array: {
20713 // delegate call to array_t::empty()
20714 return m_data.m_value.array->empty();
20715 }
20716
20717 case value_t::object: {
20718 // delegate call to object_t::empty()
20719 return m_data.m_value.object->empty();
20720 }
20721
20722 case value_t::string:
20723 case value_t::boolean:
20724 case value_t::number_integer:
20725 case value_t::number_unsigned:
20726 case value_t::number_float:
20727 case value_t::binary:
20728 case value_t::discarded:
20729 default: {
20730 // all other types are nonempty
20731 return false;
20732 }
20733 }
20734 }
20735
20738 size_type size() const noexcept {
20739 switch (m_data.m_type) {
20740 case value_t::null: {
20741 // null values are empty
20742 return 0;
20743 }
20744
20745 case value_t::array: {
20746 // delegate call to array_t::size()
20747 return m_data.m_value.array->size();
20748 }
20749
20750 case value_t::object: {
20751 // delegate call to object_t::size()
20752 return m_data.m_value.object->size();
20753 }
20754
20755 case value_t::string:
20756 case value_t::boolean:
20757 case value_t::number_integer:
20758 case value_t::number_unsigned:
20759 case value_t::number_float:
20760 case value_t::binary:
20761 case value_t::discarded:
20762 default: {
20763 // all other types have size 1
20764 return 1;
20765 }
20766 }
20767 }
20768
20771 size_type max_size() const noexcept {
20772 switch (m_data.m_type) {
20773 case value_t::array: {
20774 // delegate call to array_t::max_size()
20775 return m_data.m_value.array->max_size();
20776 }
20777
20778 case value_t::object: {
20779 // delegate call to object_t::max_size()
20780 return m_data.m_value.object->max_size();
20781 }
20782
20783 case value_t::null:
20784 case value_t::string:
20785 case value_t::boolean:
20786 case value_t::number_integer:
20787 case value_t::number_unsigned:
20788 case value_t::number_float:
20789 case value_t::binary:
20790 case value_t::discarded:
20791 default: {
20792 // all other types have max_size() == size()
20793 return size();
20794 }
20795 }
20796 }
20797
20799
20801 // modifiers //
20803
20806
20809 void clear() noexcept {
20810 switch (m_data.m_type) {
20811 case value_t::number_integer: {
20812 m_data.m_value.number_integer = 0;
20813 break;
20814 }
20815
20816 case value_t::number_unsigned: {
20817 m_data.m_value.number_unsigned = 0;
20818 break;
20819 }
20820
20821 case value_t::number_float: {
20822 m_data.m_value.number_float = 0.0;
20823 break;
20824 }
20825
20826 case value_t::boolean: {
20827 m_data.m_value.boolean = false;
20828 break;
20829 }
20830
20831 case value_t::string: {
20832 m_data.m_value.string->clear();
20833 break;
20834 }
20835
20836 case value_t::binary: {
20837 m_data.m_value.binary->clear();
20838 break;
20839 }
20840
20841 case value_t::array: {
20842 m_data.m_value.array->clear();
20843 break;
20844 }
20845
20846 case value_t::object: {
20847 m_data.m_value.object->clear();
20848 break;
20849 }
20850
20851 case value_t::null:
20852 case value_t::discarded:
20853 default:
20854 break;
20855 }
20856 }
20857
20860 void push_back(basic_json&& val) {
20861 // push_back only works for null objects or arrays
20862 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
20863 JSON_THROW(type_error::create(
20864 308, detail::concat("cannot use push_back() with ", type_name()), this));
20865 }
20866
20867 // transform null object into an array
20868 if (is_null()) {
20869 m_data.m_type = value_t::array;
20870 m_data.m_value = value_t::array;
20871 assert_invariant();
20872 }
20873
20874 // add element to array (move semantics)
20875 const auto old_capacity = m_data.m_value.array->capacity();
20876 m_data.m_value.array->push_back(std::move(val));
20877 set_parent(m_data.m_value.array->back(), old_capacity);
20878 // if val is moved from, basic_json move constructor marks it null, so we do
20879 // not call the destructor
20880 }
20881
20885 push_back(std::move(val));
20886 return *this;
20887 }
20888
20891 void push_back(const basic_json& val) {
20892 // push_back only works for null objects or arrays
20893 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
20894 JSON_THROW(type_error::create(
20895 308, detail::concat("cannot use push_back() with ", type_name()), this));
20896 }
20897
20898 // transform null object into an array
20899 if (is_null()) {
20900 m_data.m_type = value_t::array;
20901 m_data.m_value = value_t::array;
20902 assert_invariant();
20903 }
20904
20905 // add element to array
20906 const auto old_capacity = m_data.m_value.array->capacity();
20907 m_data.m_value.array->push_back(val);
20908 set_parent(m_data.m_value.array->back(), old_capacity);
20909 }
20910
20914 push_back(val);
20915 return *this;
20916 }
20917
20920 void push_back(const typename object_t::value_type& val) {
20921 // push_back only works for null objects or objects
20922 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
20923 JSON_THROW(type_error::create(
20924 308, detail::concat("cannot use push_back() with ", type_name()), this));
20925 }
20926
20927 // transform null object into an object
20928 if (is_null()) {
20929 m_data.m_type = value_t::object;
20930 m_data.m_value = value_t::object;
20931 assert_invariant();
20932 }
20933
20934 // add element to object
20935 auto res = m_data.m_value.object->insert(val);
20936 set_parent(res.first->second);
20937 }
20938
20941 reference operator+=(const typename object_t::value_type& val) {
20942 push_back(val);
20943 return *this;
20944 }
20945
20949 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) {
20950 basic_json&& key = init.begin()->moved_or_copied();
20951 push_back(typename object_t::value_type(std::move(key.get_ref<string_t&>()),
20952 (init.begin() + 1)->moved_or_copied()));
20953 } else {
20954 push_back(basic_json(init));
20955 }
20956 }
20957
20961 push_back(init);
20962 return *this;
20963 }
20964
20967 template <class... Args> reference emplace_back(Args&&... args) {
20968 // emplace_back only works for null objects or arrays
20969 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
20970 JSON_THROW(type_error::create(
20971 311, detail::concat("cannot use emplace_back() with ", type_name()), this));
20972 }
20973
20974 // transform null object into an array
20975 if (is_null()) {
20976 m_data.m_type = value_t::array;
20977 m_data.m_value = value_t::array;
20978 assert_invariant();
20979 }
20980
20981 // add element to array (perfect forwarding)
20982 const auto old_capacity = m_data.m_value.array->capacity();
20983 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
20984 return set_parent(m_data.m_value.array->back(), old_capacity);
20985 }
20986
20989 template <class... Args> std::pair<iterator, bool> emplace(Args&&... args) {
20990 // emplace only works for null objects or arrays
20991 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
20992 JSON_THROW(type_error::create(
20993 311, detail::concat("cannot use emplace() with ", type_name()), this));
20994 }
20995
20996 // transform null object into an object
20997 if (is_null()) {
20998 m_data.m_type = value_t::object;
20999 m_data.m_value = value_t::object;
21000 assert_invariant();
21001 }
21002
21003 // add element to array (perfect forwarding)
21004 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
21005 set_parent(res.first->second);
21006
21007 // create result iterator and set iterator to the result of emplace
21008 auto it = begin();
21009 it.m_it.object_iterator = res.first;
21010
21011 // return pair of iterator and boolean
21012 return {it, res.second};
21013 }
21014
21018 template <typename... Args> iterator insert_iterator(const_iterator pos, Args&&... args) {
21019 iterator result(this);
21020 JSON_ASSERT(m_data.m_value.array != nullptr);
21021
21022 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
21023 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21024 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
21025
21026 // This could have been written as:
21027 // result.m_it.array_iterator =
21028 // m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); but the
21029 // return value of insert is missing in GCC 4.8, so it is written this way
21030 // instead.
21031
21032 set_parents();
21033 return result;
21034 }
21035
21039 // insert only works for arrays
21040 if (JSON_HEDLEY_LIKELY(is_array())) {
21041 // check if iterator pos fits to this JSON value
21042 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21043 JSON_THROW(
21044 invalid_iterator::create(202, "iterator does not fit current value", this));
21045 }
21046
21047 // insert to array and return iterator
21048 return insert_iterator(pos, val);
21049 }
21050
21051 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()),
21052 this));
21053 }
21054
21057 iterator insert(const_iterator pos, basic_json&& val) { return insert(pos, val); }
21058
21062 // insert only works for arrays
21063 if (JSON_HEDLEY_LIKELY(is_array())) {
21064 // check if iterator pos fits to this JSON value
21065 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21066 JSON_THROW(
21067 invalid_iterator::create(202, "iterator does not fit current value", this));
21068 }
21069
21070 // insert to array and return iterator
21071 return insert_iterator(pos, cnt, val);
21072 }
21073
21074 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()),
21075 this));
21076 }
21077
21081 // insert only works for arrays
21082 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21083 JSON_THROW(type_error::create(
21084 309, detail::concat("cannot use insert() with ", type_name()), this));
21085 }
21086
21087 // check if iterator pos fits to this JSON value
21088 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21089 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21090 }
21091
21092 // check if range iterators belong to the same JSON object
21093 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21094 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21095 }
21096
21097 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) {
21098 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container",
21099 this));
21100 }
21101
21102 // insert to array and return iterator
21103 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
21104 }
21105
21109 // insert only works for arrays
21110 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21111 JSON_THROW(type_error::create(
21112 309, detail::concat("cannot use insert() with ", type_name()), this));
21113 }
21114
21115 // check if iterator pos fits to this JSON value
21116 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) {
21117 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21118 }
21119
21120 // insert to array and return iterator
21121 return insert_iterator(pos, ilist.begin(), ilist.end());
21122 }
21123
21127 // insert only works for objects
21128 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21129 JSON_THROW(type_error::create(
21130 309, detail::concat("cannot use insert() with ", type_name()), this));
21131 }
21132
21133 // check if range iterators belong to the same JSON object
21134 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21135 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21136 }
21137
21138 // passed iterators must belong to objects
21139 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21140 JSON_THROW(invalid_iterator::create(
21141 202, "iterators first and last must point to objects", this));
21142 }
21143
21144 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
21145 }
21146
21150 void update(const_reference j, bool merge_objects = false) {
21151 update(j.begin(), j.end(), merge_objects);
21152 }
21153
21157 void update(const_iterator first, const_iterator last, bool merge_objects = false) {
21158 // implicitly convert null value to an empty object
21159 if (is_null()) {
21160 m_data.m_type = value_t::object;
21161 m_data.m_value.object = create<object_t>();
21162 assert_invariant();
21163 }
21164
21165 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21166 JSON_THROW(type_error::create(
21167 312, detail::concat("cannot use update() with ", type_name()), this));
21168 }
21169
21170 // check if range iterators belong to the same JSON object
21171 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21172 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
21173 }
21174
21175 // passed iterators must belong to objects
21176 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21177 JSON_THROW(type_error::create(
21178 312, detail::concat("cannot use update() with ", first.m_object->type_name()),
21179 first.m_object));
21180 }
21181
21182 for (auto it = first; it != last; ++it) {
21183 if (merge_objects && it.value().is_object()) {
21184 auto it2 = m_data.m_value.object->find(it.key());
21185 if (it2 != m_data.m_value.object->end()) {
21186 it2->second.update(it.value(), true);
21187 continue;
21188 }
21189 }
21190 m_data.m_value.object->operator[](it.key()) = it.value();
21191#if JSON_DIAGNOSTICS
21192 m_data.m_value.object->operator[](it.key()).m_parent = this;
21193#endif
21194 }
21195 }
21196
21199 void swap(reference other) noexcept(
21200 std::is_nothrow_move_constructible<value_t>::value &&
21201 std::is_nothrow_move_assignable<value_t>::value &&
21202 std::is_nothrow_move_constructible<json_value>::
21203 value && // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21204 std::is_nothrow_move_assignable<json_value>::value) {
21205 std::swap(m_data.m_type, other.m_data.m_type);
21206 std::swap(m_data.m_value, other.m_data.m_value);
21207
21208 set_parents();
21209 other.set_parents();
21210 assert_invariant();
21211 }
21212
21215 friend void swap(reference left, reference right) noexcept(
21216 std::is_nothrow_move_constructible<value_t>::value &&
21217 std::is_nothrow_move_assignable<value_t>::value &&
21218 std::is_nothrow_move_constructible<json_value>::
21219 value && // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21220 std::is_nothrow_move_assignable<json_value>::value) {
21221 left.swap(right);
21222 }
21223
21226 void swap(
21227 array_t&
21228 other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21229 {
21230 // swap only works for arrays
21231 if (JSON_HEDLEY_LIKELY(is_array())) {
21232 using std::swap;
21233 swap(*(m_data.m_value.array), other);
21234 } else {
21235 JSON_THROW(type_error::create(
21236 310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
21237 }
21238 }
21239
21242 void swap(
21243 object_t&
21244 other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21245 {
21246 // swap only works for objects
21247 if (JSON_HEDLEY_LIKELY(is_object())) {
21248 using std::swap;
21249 swap(*(m_data.m_value.object), other);
21250 } else {
21251 JSON_THROW(type_error::create(
21252 310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
21253 }
21254 }
21255
21258 void swap(
21259 string_t&
21260 other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21261 {
21262 // swap only works for strings
21263 if (JSON_HEDLEY_LIKELY(is_string())) {
21264 using std::swap;
21265 swap(*(m_data.m_value.string), other);
21266 } else {
21267 JSON_THROW(type_error::create(
21268 310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
21269 }
21270 }
21271
21274 void swap(
21275 binary_t&
21276 other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
21277 {
21278 // swap only works for strings
21279 if (JSON_HEDLEY_LIKELY(is_binary())) {
21280 using std::swap;
21281 swap(*(m_data.m_value.binary), other);
21282 } else {
21283 JSON_THROW(type_error::create(
21284 310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
21285 }
21286 }
21287
21290 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
21291 {
21292 // swap only works for strings
21293 if (JSON_HEDLEY_LIKELY(is_binary())) {
21294 using std::swap;
21295 swap(*(m_data.m_value.binary), other);
21296 } else {
21297 JSON_THROW(type_error::create(
21298 310,
21299 detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()),
21300 this));
21301 }
21302 }
21303
21305
21307 // lexicographical comparison operators //
21309
21312
21313 // note parentheses around operands are necessary; see
21314 // https://github.com/nlohmann/json/issues/1530
21315#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
21316 const auto lhs_type = lhs.type(); \
21317 const auto rhs_type = rhs.type(); \
21318 \
21319 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
21320 { \
21321 switch (lhs_type) { \
21322 case value_t::array: \
21323 return (*lhs.m_data.m_value.array)op(*rhs.m_data.m_value.array); \
21324 \
21325 case value_t::object: \
21326 return (*lhs.m_data.m_value.object)op(*rhs.m_data.m_value.object); \
21327 \
21328 case value_t::null: \
21329 return (null_result); \
21330 \
21331 case value_t::string: \
21332 return (*lhs.m_data.m_value.string)op(*rhs.m_data.m_value.string); \
21333 \
21334 case value_t::boolean: \
21335 return (lhs.m_data.m_value.boolean)op(rhs.m_data.m_value.boolean); \
21336 \
21337 case value_t::number_integer: \
21338 return (lhs.m_data.m_value.number_integer)op(rhs.m_data.m_value.number_integer); \
21339 \
21340 case value_t::number_unsigned: \
21341 return (lhs.m_data.m_value.number_unsigned)op(rhs.m_data.m_value.number_unsigned); \
21342 \
21343 case value_t::number_float: \
21344 return (lhs.m_data.m_value.number_float)op(rhs.m_data.m_value.number_float); \
21345 \
21346 case value_t::binary: \
21347 return (*lhs.m_data.m_value.binary)op(*rhs.m_data.m_value.binary); \
21348 \
21349 case value_t::discarded: \
21350 default: \
21351 return (unordered_result); \
21352 } \
21353 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) { \
21354 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) \
21355 op rhs.m_data.m_value.number_float; \
21356 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) { \
21357 return lhs.m_data.m_value.number_float op static_cast<number_float_t>( \
21358 rhs.m_data.m_value.number_integer); \
21359 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) { \
21360 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) \
21361 op rhs.m_data.m_value.number_float; \
21362 } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) { \
21363 return lhs.m_data.m_value.number_float op static_cast<number_float_t>( \
21364 rhs.m_data.m_value.number_unsigned); \
21365 } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) { \
21366 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) \
21367 op rhs.m_data.m_value.number_integer; \
21368 } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) { \
21369 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>( \
21370 rhs.m_data.m_value.number_unsigned); \
21371 } else if (compares_unordered(lhs, rhs)) { \
21372 return (unordered_result); \
21373 } \
21374 \
21375 return (default_result);
21376
21377 JSON_PRIVATE_UNLESS_TESTED :
21378 // returns true if:
21379 // - any operand is NaN and the other operand is of number type
21380 // - any operand is discarded
21381 // in legacy mode, discarded values are considered ordered if
21382 // an operation is computed as an odd number of inverses of others
21383 static bool
21384 compares_unordered(const_reference lhs, const_reference rhs,
21385 bool inverse = false) noexcept {
21386 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) &&
21387 rhs.is_number()) ||
21388 (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) &&
21389 lhs.is_number())) {
21390 return true;
21391 }
21392#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
21393 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
21394#else
21395 static_cast<void>(inverse);
21396 return lhs.is_discarded() || rhs.is_discarded();
21397#endif
21398 }
21399
21400 private:
21401 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept {
21402 return compares_unordered(*this, rhs, inverse);
21403 }
21404
21405 public:
21406#if JSON_HAS_THREE_WAY_COMPARISON
21409 bool operator==(const_reference rhs) const noexcept {
21410#ifdef __GNUC__
21411#pragma GCC diagnostic push
21412#pragma GCC diagnostic ignored "-Wfloat-equal"
21413#endif
21414 const_reference lhs = *this;
21415 JSON_IMPLEMENT_OPERATOR(==, true, false, false)
21416#ifdef __GNUC__
21417#pragma GCC diagnostic pop
21418#endif
21419 }
21420
21423 template <typename ScalarType>
21424 requires std::is_scalar_v<ScalarType>
21425 bool operator==(ScalarType rhs) const noexcept {
21426 return *this == basic_json(rhs);
21427 }
21428
21431 bool operator!=(const_reference rhs) const noexcept {
21432 if (compares_unordered(rhs, true)) {
21433 return false;
21434 }
21435 return !operator==(rhs);
21436 }
21437
21440 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
21441 {
21442 const_reference lhs = *this;
21443 // default_result is used if we cannot compare values. In that case,
21444 // we compare types.
21445 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
21446 std::partial_ordering::equivalent, std::partial_ordering::unordered,
21447 lhs_type <=> rhs_type) // *NOPAD*
21448 }
21449
21452 template <typename ScalarType>
21453 requires std::is_scalar_v<ScalarType>
21454 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
21455 {
21456 return *this <=> basic_json(rhs); // *NOPAD*
21457 }
21458
21459#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
21460 // all operators that are computed as an odd number of inverses of others
21461 // need to be overloaded to emulate the legacy comparison behavior
21462
21465 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
21466 bool operator<=(const_reference rhs) const noexcept {
21467 if (compares_unordered(rhs, true)) {
21468 return false;
21469 }
21470 return !(rhs < *this);
21471 }
21472
21475 template <typename ScalarType>
21476 requires std::is_scalar_v<ScalarType>
21477 bool operator<=(ScalarType rhs) const noexcept {
21478 return *this <= basic_json(rhs);
21479 }
21480
21483 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
21484 bool operator>=(const_reference rhs) const noexcept {
21485 if (compares_unordered(rhs, true)) {
21486 return false;
21487 }
21488 return !(*this < rhs);
21489 }
21490
21493 template <typename ScalarType>
21494 requires std::is_scalar_v<ScalarType>
21495 bool operator>=(ScalarType rhs) const noexcept {
21496 return *this >= basic_json(rhs);
21497 }
21498#endif
21499#else
21502 friend bool operator==(const_reference lhs, const_reference rhs) noexcept {
21503#ifdef __GNUC__
21504#pragma GCC diagnostic push
21505#pragma GCC diagnostic ignored "-Wfloat-equal"
21506#endif
21507 JSON_IMPLEMENT_OPERATOR(==, true, false, false)
21508#ifdef __GNUC__
21509#pragma GCC diagnostic pop
21510#endif
21511 }
21512
21515 template <typename ScalarType,
21516 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21517 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept {
21518 return lhs == basic_json(rhs);
21519 }
21520
21523 template <typename ScalarType,
21524 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21525 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept {
21526 return basic_json(lhs) == rhs;
21527 }
21528
21531 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept {
21532 if (compares_unordered(lhs, rhs, true)) {
21533 return false;
21534 }
21535 return !(lhs == rhs);
21536 }
21537
21540 template <typename ScalarType,
21541 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21542 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept {
21543 return lhs != basic_json(rhs);
21544 }
21545
21548 template <typename ScalarType,
21549 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21550 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept {
21551 return basic_json(lhs) != rhs;
21552 }
21553
21556 friend bool operator<(const_reference lhs, const_reference rhs) noexcept {
21557 // default_result is used if we cannot compare values. In that case,
21558 // we compare types. Note we have to call the operator explicitly,
21559 // because MSVC has problems otherwise.
21560 JSON_IMPLEMENT_OPERATOR(<, false, false, operator<(lhs_type, rhs_type))
21561 }
21562
21565 template <typename ScalarType,
21566 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21567 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept {
21568 return lhs < basic_json(rhs);
21569 }
21570
21573 template <typename ScalarType,
21574 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21575 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept {
21576 return basic_json(lhs) < rhs;
21577 }
21578
21581 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept {
21582 if (compares_unordered(lhs, rhs, true)) {
21583 return false;
21584 }
21585 return !(rhs < lhs);
21586 }
21587
21590 template <typename ScalarType,
21591 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21592 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept {
21593 return lhs <= basic_json(rhs);
21594 }
21595
21598 template <typename ScalarType,
21599 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21600 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept {
21601 return basic_json(lhs) <= rhs;
21602 }
21603
21606 friend bool operator>(const_reference lhs, const_reference rhs) noexcept {
21607 // double inverse
21608 if (compares_unordered(lhs, rhs)) {
21609 return false;
21610 }
21611 return !(lhs <= rhs);
21612 }
21613
21616 template <typename ScalarType,
21617 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21618 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept {
21619 return lhs > basic_json(rhs);
21620 }
21621
21624 template <typename ScalarType,
21625 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21626 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept {
21627 return basic_json(lhs) > rhs;
21628 }
21629
21632 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept {
21633 if (compares_unordered(lhs, rhs, true)) {
21634 return false;
21635 }
21636 return !(lhs < rhs);
21637 }
21638
21641 template <typename ScalarType,
21642 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21643 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept {
21644 return lhs >= basic_json(rhs);
21645 }
21646
21649 template <typename ScalarType,
21650 typename std::enable_if<std::is_scalar<ScalarType>::value, int>::type = 0>
21651 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept {
21652 return basic_json(lhs) >= rhs;
21653 }
21654#endif
21655
21656#undef JSON_IMPLEMENT_OPERATOR
21657
21659
21661 // serialization //
21663
21666#ifndef JSON_NO_IO
21669 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) {
21670 // read width member and use it as indentation parameter if nonzero
21671 const bool pretty_print = o.width() > 0;
21672 const auto indentation = pretty_print ? o.width() : 0;
21673
21674 // reset width to 0 for subsequent calls to this stream
21675 o.width(0);
21676
21677 // do the actual serialization
21678 serializer s(detail::output_adapter<char>(o), o.fill());
21679 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
21680 return o;
21681 }
21682
21689 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
21690 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) { return o << j; }
21691#endif // JSON_NO_IO
21693
21695 // deserialization //
21697
21700
21703 template <typename InputType>
21704 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
21705 parse(InputType&& i, const parser_callback_t cb = nullptr, const bool allow_exceptions = true,
21706 const bool ignore_comments = false) {
21707 basic_json result;
21708 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions,
21709 ignore_comments)
21710 .parse(true, result);
21711 return result;
21712 }
21713
21716 template <typename IteratorType>
21717 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
21718 parse(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr,
21719 const bool allow_exceptions = true, const bool ignore_comments = false) {
21720 basic_json result;
21721 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions,
21722 ignore_comments)
21723 .parse(true, result);
21724 return result;
21725 }
21726
21727 JSON_HEDLEY_WARN_UNUSED_RESULT
21728 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
21729 static basic_json parse(detail::span_input_adapter&& i, const parser_callback_t cb = nullptr,
21730 const bool allow_exceptions = true,
21731 const bool ignore_comments = false) {
21732 basic_json result;
21733 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
21734 return result;
21735 }
21736
21739 template <typename InputType>
21740 static bool accept(InputType&& i, const bool ignore_comments = false) {
21741 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false,
21742 ignore_comments)
21743 .accept(true);
21744 }
21745
21748 template <typename IteratorType>
21749 static bool accept(IteratorType first, IteratorType last, const bool ignore_comments = false) {
21750 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false,
21751 ignore_comments)
21752 .accept(true);
21753 }
21754
21755 JSON_HEDLEY_WARN_UNUSED_RESULT
21756 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
21757 static bool accept(detail::span_input_adapter&& i, const bool ignore_comments = false) {
21758 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
21759 }
21760
21763 template <typename InputType, typename SAX>
21764 JSON_HEDLEY_NON_NULL(2)
21765 static bool sax_parse(InputType&& i, SAX* sax, input_format_t format = input_format_t::json,
21766 const bool strict = true, const bool ignore_comments = false) {
21767 auto ia = detail::input_adapter(std::forward<InputType>(i));
21768 return format == input_format_t::json
21769 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
21770 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format)
21771 .sax_parse(format, sax, strict);
21772 }
21773
21776 template <class IteratorType, class SAX>
21777 JSON_HEDLEY_NON_NULL(3)
21778 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
21779 input_format_t format = input_format_t::json, const bool strict = true,
21780 const bool ignore_comments = false) {
21781 auto ia = detail::input_adapter(std::move(first), std::move(last));
21782 return format == input_format_t::json
21783 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
21785 .sax_parse(format, sax, strict);
21786 }
21787
21793 template <typename SAX>
21794 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
21795 JSON_HEDLEY_NON_NULL(2) static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
21796 input_format_t format = input_format_t::json,
21797 const bool strict = true,
21798 const bool ignore_comments = false) {
21799 auto ia = i.get();
21800 return format == input_format_t::json
21801 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21802 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
21803 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
21805 .sax_parse(format, sax, strict);
21806 }
21807#ifndef JSON_NO_IO
21815 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
21816 friend std::istream& operator<<(basic_json& j, std::istream& i) { return operator>>(i, j); }
21817
21820 friend std::istream& operator>>(std::istream& i, basic_json& j) {
21821 parser(detail::input_adapter(i)).parse(false, j);
21822 return i;
21823 }
21824#endif // JSON_NO_IO
21826
21828 // convenience functions //
21830
21833 JSON_HEDLEY_RETURNS_NON_NULL
21834 const char* type_name() const noexcept {
21835 switch (m_data.m_type) {
21836 case value_t::null:
21837 return "null";
21838 case value_t::object:
21839 return "object";
21840 case value_t::array:
21841 return "array";
21842 case value_t::string:
21843 return "string";
21844 case value_t::boolean:
21845 return "boolean";
21846 case value_t::binary:
21847 return "binary";
21848 case value_t::discarded:
21849 return "discarded";
21850 case value_t::number_integer:
21851 case value_t::number_unsigned:
21852 case value_t::number_float:
21853 default:
21854 return "number";
21855 }
21856 }
21857
21858 JSON_PRIVATE_UNLESS_TESTED :
21860 // member variables //
21862
21863 struct data {
21865 value_t m_type = value_t::null;
21866
21868 json_value m_value = {};
21869
21870 data(const value_t v) : m_type(v), m_value(v) {}
21871
21872 data(size_type cnt, const basic_json& val) : m_type(value_t::array) {
21873 m_value.array = create<array_t>(cnt, val);
21874 }
21875
21876 data() noexcept = default;
21877 data(data&&) noexcept = default;
21878 data(const data&) noexcept = delete;
21879 data& operator=(data&&) noexcept = delete;
21880 data& operator=(const data&) noexcept = delete;
21881
21882 ~data() noexcept { m_value.destroy(m_type); }
21883 };
21884
21885 data m_data = {};
21886
21887#if JSON_DIAGNOSTICS
21889 basic_json* m_parent = nullptr;
21890#endif
21891
21893 // binary serialization/deserialization //
21895
21898
21899 public:
21902 static std::vector<std::uint8_t> to_cbor(const basic_json& j) {
21903 std::vector<std::uint8_t> result;
21904 to_cbor(j, result);
21905 return result;
21906 }
21907
21911 binary_writer<std::uint8_t>(o).write_cbor(j);
21912 }
21913
21917 binary_writer<char>(o).write_cbor(j);
21918 }
21919
21922 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) {
21923 std::vector<std::uint8_t> result;
21924 to_msgpack(j, result);
21925 return result;
21926 }
21927
21931 binary_writer<std::uint8_t>(o).write_msgpack(j);
21932 }
21933
21937 binary_writer<char>(o).write_msgpack(j);
21938 }
21939
21942 static std::vector<std::uint8_t> to_ubjson(const basic_json& j, const bool use_size = false,
21943 const bool use_type = false) {
21944 std::vector<std::uint8_t> result;
21945 to_ubjson(j, result, use_size, use_type);
21946 return result;
21947 }
21948
21952 const bool use_size = false, const bool use_type = false) {
21953 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
21954 }
21955
21959 const bool use_size = false, const bool use_type = false) {
21960 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
21961 }
21962
21965 static std::vector<std::uint8_t> to_bjdata(const basic_json& j, const bool use_size = false,
21966 const bool use_type = false) {
21967 std::vector<std::uint8_t> result;
21968 to_bjdata(j, result, use_size, use_type);
21969 return result;
21970 }
21971
21975 const bool use_size = false, const bool use_type = false) {
21976 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
21977 }
21978
21982 const bool use_size = false, const bool use_type = false) {
21983 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
21984 }
21985
21988 static std::vector<std::uint8_t> to_bson(const basic_json& j) {
21989 std::vector<std::uint8_t> result;
21990 to_bson(j, result);
21991 return result;
21992 }
21993
21997 binary_writer<std::uint8_t>(o).write_bson(j);
21998 }
21999
22003 binary_writer<char>(o).write_bson(j);
22004 }
22005
22008 template <typename InputType>
22009 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22010 from_cbor(InputType&& i, const bool strict = true, const bool allow_exceptions = true,
22011 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22012 basic_json result;
22013 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22014 auto ia = detail::input_adapter(std::forward<InputType>(i));
22015 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor)
22016 .sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22017 return res ? result : basic_json(value_t::discarded);
22018 }
22019
22022 template <typename IteratorType>
22023 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22024 from_cbor(IteratorType first, IteratorType last, const bool strict = true,
22025 const bool allow_exceptions = true,
22026 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22027 basic_json result;
22028 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22029 auto ia = detail::input_adapter(std::move(first), std::move(last));
22030 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor)
22031 .sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22032 return res ? result : basic_json(value_t::discarded);
22033 }
22034
22035 template <typename T>
22036 JSON_HEDLEY_WARN_UNUSED_RESULT
22037 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) static basic_json
22038 from_cbor(const T* ptr, std::size_t len, const bool strict = true,
22039 const bool allow_exceptions = true,
22040 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22041 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
22042 }
22043
22044 JSON_HEDLEY_WARN_UNUSED_RESULT
22045 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22046 static basic_json from_cbor(detail::span_input_adapter&& i, const bool strict = true,
22047 const bool allow_exceptions = true,
22048 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22049 basic_json result;
22050 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22051 auto ia = i.get();
22052 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22053 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor)
22054 .sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22055 return res ? result : basic_json(value_t::discarded);
22056 }
22057
22060 template <typename InputType>
22061 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22062 from_msgpack(InputType&& i, const bool strict = true, const bool allow_exceptions = true) {
22063 basic_json result;
22064 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22065 auto ia = detail::input_adapter(std::forward<InputType>(i));
22066 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack)
22067 .sax_parse(input_format_t::msgpack, &sdp, strict);
22068 return res ? result : basic_json(value_t::discarded);
22069 }
22070
22073 template <typename IteratorType>
22074 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22075 from_msgpack(IteratorType first, IteratorType last, const bool strict = true,
22076 const bool allow_exceptions = true) {
22077 basic_json result;
22078 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22079 auto ia = detail::input_adapter(std::move(first), std::move(last));
22080 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack)
22081 .sax_parse(input_format_t::msgpack, &sdp, strict);
22082 return res ? result : basic_json(value_t::discarded);
22083 }
22084
22085 template <typename T>
22086 JSON_HEDLEY_WARN_UNUSED_RESULT
22087 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) static basic_json
22088 from_msgpack(const T* ptr, std::size_t len, const bool strict = true,
22089 const bool allow_exceptions = true) {
22090 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
22091 }
22092
22093 JSON_HEDLEY_WARN_UNUSED_RESULT
22094 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22095 static basic_json from_msgpack(detail::span_input_adapter&& i, const bool strict = true,
22096 const bool allow_exceptions = true) {
22097 basic_json result;
22098 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22099 auto ia = i.get();
22100 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22101 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack)
22102 .sax_parse(input_format_t::msgpack, &sdp, strict);
22103 return res ? result : basic_json(value_t::discarded);
22104 }
22105
22108 template <typename InputType>
22109 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22110 from_ubjson(InputType&& i, const bool strict = true, const bool allow_exceptions = true) {
22111 basic_json result;
22112 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22113 auto ia = detail::input_adapter(std::forward<InputType>(i));
22114 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson)
22115 .sax_parse(input_format_t::ubjson, &sdp, strict);
22116 return res ? result : basic_json(value_t::discarded);
22117 }
22118
22121 template <typename IteratorType>
22122 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22123 from_ubjson(IteratorType first, IteratorType last, const bool strict = true,
22124 const bool allow_exceptions = true) {
22125 basic_json result;
22126 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22127 auto ia = detail::input_adapter(std::move(first), std::move(last));
22128 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson)
22129 .sax_parse(input_format_t::ubjson, &sdp, strict);
22130 return res ? result : basic_json(value_t::discarded);
22131 }
22132
22133 template <typename T>
22134 JSON_HEDLEY_WARN_UNUSED_RESULT
22135 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) static basic_json
22136 from_ubjson(const T* ptr, std::size_t len, const bool strict = true,
22137 const bool allow_exceptions = true) {
22138 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
22139 }
22140
22141 JSON_HEDLEY_WARN_UNUSED_RESULT
22142 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
22143 static basic_json from_ubjson(detail::span_input_adapter&& i, const bool strict = true,
22144 const bool allow_exceptions = true) {
22145 basic_json result;
22146 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22147 auto ia = i.get();
22148 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22149 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson)
22150 .sax_parse(input_format_t::ubjson, &sdp, strict);
22151 return res ? result : basic_json(value_t::discarded);
22152 }
22153
22156 template <typename InputType>
22157 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22158 from_bjdata(InputType&& i, const bool strict = true, const bool allow_exceptions = true) {
22159 basic_json result;
22160 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22161 auto ia = detail::input_adapter(std::forward<InputType>(i));
22162 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata)
22163 .sax_parse(input_format_t::bjdata, &sdp, strict);
22164 return res ? result : basic_json(value_t::discarded);
22165 }
22166
22169 template <typename IteratorType>
22170 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22171 from_bjdata(IteratorType first, IteratorType last, const bool strict = true,
22172 const bool allow_exceptions = true) {
22173 basic_json result;
22174 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22175 auto ia = detail::input_adapter(std::move(first), std::move(last));
22176 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata)
22177 .sax_parse(input_format_t::bjdata, &sdp, strict);
22178 return res ? result : basic_json(value_t::discarded);
22179 }
22180
22183 template <typename InputType>
22184 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22185 from_bson(InputType&& i, const bool strict = true, const bool allow_exceptions = true) {
22186 basic_json result;
22187 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22188 auto ia = detail::input_adapter(std::forward<InputType>(i));
22189 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson)
22190 .sax_parse(input_format_t::bson, &sdp, strict);
22191 return res ? result : basic_json(value_t::discarded);
22192 }
22193
22196 template <typename IteratorType>
22197 JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json
22198 from_bson(IteratorType first, IteratorType last, const bool strict = true,
22199 const bool allow_exceptions = true) {
22200 basic_json result;
22201 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22202 auto ia = detail::input_adapter(std::move(first), std::move(last));
22203 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson)
22204 .sax_parse(input_format_t::bson, &sdp, strict);
22205 return res ? result : basic_json(value_t::discarded);
22206 }
22207
22208 template <typename T>
22209 JSON_HEDLEY_WARN_UNUSED_RESULT
22210 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) static basic_json
22211 from_bson(const T* ptr, std::size_t len, const bool strict = true,
22212 const bool allow_exceptions = true) {
22213 return from_bson(ptr, ptr + len, strict, allow_exceptions);
22214 }
22215
22216 JSON_HEDLEY_WARN_UNUSED_RESULT
22217 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
22218 static basic_json from_bson(detail::span_input_adapter&& i, const bool strict = true,
22219 const bool allow_exceptions = true) {
22220 basic_json result;
22221 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
22222 auto ia = i.get();
22223 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
22224 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson)
22225 .sax_parse(input_format_t::bson, &sdp, strict);
22226 return res ? result : basic_json(value_t::discarded);
22227 }
22229
22231 // JSON Pointer support //
22233
22236
22239 reference operator[](const json_pointer& ptr) { return ptr.get_unchecked(this); }
22240
22241 template <typename BasicJsonType,
22242 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22243 JSON_HEDLEY_DEPRECATED_FOR(
22244 3.11.0, basic_json::json_pointer or
22245 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22246 reference
22247 operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
22248 return ptr.get_unchecked(this);
22249 }
22250
22253 const_reference operator[](const json_pointer& ptr) const { return ptr.get_unchecked(this); }
22254
22255 template <typename BasicJsonType,
22256 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22257 JSON_HEDLEY_DEPRECATED_FOR(
22258 3.11.0, basic_json::json_pointer or
22259 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22260 const_reference
22261 operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
22262 return ptr.get_unchecked(this);
22263 }
22264
22267 reference at(const json_pointer& ptr) { return ptr.get_checked(this); }
22268
22269 template <typename BasicJsonType,
22270 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22271 JSON_HEDLEY_DEPRECATED_FOR(
22272 3.11.0, basic_json::json_pointer or
22273 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22274 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
22275 return ptr.get_checked(this);
22276 }
22277
22280 const_reference at(const json_pointer& ptr) const { return ptr.get_checked(this); }
22281
22282 template <typename BasicJsonType,
22283 detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22284 JSON_HEDLEY_DEPRECATED_FOR(
22285 3.11.0, basic_json::json_pointer or
22286 nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22287 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const {
22288 return ptr.get_checked(this);
22289 }
22290
22293 basic_json flatten() const {
22294 basic_json result(value_t::object);
22295 json_pointer::flatten("", *this, result);
22296 return result;
22297 }
22298
22301 basic_json unflatten() const { return json_pointer::unflatten(*this); }
22302
22304
22306 // JSON Patch functions //
22308
22311
22314 void patch_inplace(const basic_json& json_patch) {
22315 basic_json& result = *this;
22316 // the valid JSON Patch operations
22317 enum class patch_operations { add, remove, replace, move, copy, test, invalid };
22318
22319 const auto get_op = [](const std::string& op) {
22320 if (op == "add") {
22321 return patch_operations::add;
22322 }
22323 if (op == "remove") {
22324 return patch_operations::remove;
22325 }
22326 if (op == "replace") {
22327 return patch_operations::replace;
22328 }
22329 if (op == "move") {
22330 return patch_operations::move;
22331 }
22332 if (op == "copy") {
22333 return patch_operations::copy;
22334 }
22335 if (op == "test") {
22336 return patch_operations::test;
22337 }
22338
22339 return patch_operations::invalid;
22340 };
22341
22342 // wrapper for "add" operation; add value at ptr
22343 const auto operation_add = [&result](json_pointer& ptr, basic_json val) {
22344 // adding to the root of the target document means replacing it
22345 if (ptr.empty()) {
22346 result = val;
22347 return;
22348 }
22349
22350 // make sure the top element of the pointer exists
22351 json_pointer const top_pointer = ptr.top();
22352 if (top_pointer != ptr) {
22353 result.at(top_pointer);
22354 }
22355
22356 // get reference to parent of JSON pointer ptr
22357 const auto last_path = ptr.back();
22358 ptr.pop_back();
22359 // parent must exist when performing patch add per RFC6902 specs
22360 basic_json& parent = result.at(ptr);
22361
22362 switch (parent.m_data.m_type) {
22363 case value_t::null:
22364 case value_t::object: {
22365 // use operator[] to add value
22366 parent[last_path] = val;
22367 break;
22368 }
22369
22370 case value_t::array: {
22371 if (last_path == "-") {
22372 // special case: append to back
22373 parent.push_back(val);
22374 } else {
22375 const auto idx =
22376 json_pointer::template array_index<basic_json_t>(last_path);
22377 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) {
22378 // avoid undefined behavior
22379 JSON_THROW(out_of_range::create(401,
22380 detail::concat("array index ",
22381 std::to_string(idx),
22382 " is out of range"),
22383 &parent));
22384 }
22385
22386 // default case: insert add offset
22387 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
22388 }
22389 break;
22390 }
22391
22392 // if there exists a parent it cannot be primitive
22393 case value_t::string: // LCOV_EXCL_LINE
22394 case value_t::boolean: // LCOV_EXCL_LINE
22395 case value_t::number_integer: // LCOV_EXCL_LINE
22396 case value_t::number_unsigned: // LCOV_EXCL_LINE
22397 case value_t::number_float: // LCOV_EXCL_LINE
22398 case value_t::binary: // LCOV_EXCL_LINE
22399 case value_t::discarded: // LCOV_EXCL_LINE
22400 default: // LCOV_EXCL_LINE
22401 JSON_ASSERT(
22402 false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
22403 // LCOV_EXCL_LINE
22404 }
22405 };
22406
22407 // wrapper for "remove" operation; remove value at ptr
22408 const auto operation_remove = [this, &result](json_pointer& ptr) {
22409 // get reference to parent of JSON pointer ptr
22410 const auto last_path = ptr.back();
22411 ptr.pop_back();
22412 basic_json& parent = result.at(ptr);
22413
22414 // remove child
22415 if (parent.is_object()) {
22416 // perform range check
22417 auto it = parent.find(last_path);
22418 if (JSON_HEDLEY_LIKELY(it != parent.end())) {
22419 parent.erase(it);
22420 } else {
22421 JSON_THROW(out_of_range::create(
22422 403, detail::concat("key '", last_path, "' not found"), this));
22423 }
22424 } else if (parent.is_array()) {
22425 // note erase performs range check
22426 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
22427 }
22428 };
22429
22430 // type check: top level value must be an array
22431 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) {
22432 JSON_THROW(
22433 parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
22434 }
22435
22436 // iterate and apply the operations
22437 for (const auto& val : json_patch) {
22438 // wrapper to get a value for an operation
22439 const auto get_value = [&val](const std::string& op, const std::string& member,
22440 bool string_type) -> basic_json& {
22441 // find value
22442 auto it = val.m_data.m_value.object->find(member);
22443
22444 // context-sensitive error message
22445 const auto error_msg =
22446 (op == "op") ? "operation"
22447 : detail::concat(
22448 "operation '", op,
22449 '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
22450
22451 // check if desired value is present
22452 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) {
22453 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
22454 JSON_THROW(parse_error::create(
22455 105, 0, detail::concat(error_msg, " must have member '", member, "'"),
22456 &val));
22457 }
22458
22459 // check if result is of type string
22460 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) {
22461 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
22462 JSON_THROW(parse_error::create(
22463 105, 0,
22464 detail::concat(error_msg, " must have string member '", member, "'"),
22465 &val));
22466 }
22467
22468 // no error: return value
22469 return it->second;
22470 };
22471
22472 // type check: every element of the array must be an object
22473 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) {
22474 JSON_THROW(
22475 parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
22476 }
22477
22478 // collect mandatory members
22479 const auto op = get_value("op", "op", true).template get<std::string>();
22480 const auto path = get_value(op, "path", true).template get<std::string>();
22481 json_pointer ptr(path);
22482
22483 switch (get_op(op)) {
22484 case patch_operations::add: {
22485 operation_add(ptr, get_value("add", "value", false));
22486 break;
22487 }
22488
22489 case patch_operations::remove: {
22490 operation_remove(ptr);
22491 break;
22492 }
22493
22494 case patch_operations::replace: {
22495 // the "path" location must exist - use at()
22496 result.at(ptr) = get_value("replace", "value", false);
22497 break;
22498 }
22499
22500 case patch_operations::move: {
22501 const auto from_path =
22502 get_value("move", "from", true).template get<std::string>();
22503 json_pointer from_ptr(from_path);
22504
22505 // the "from" location must exist - use at()
22506 basic_json const v = result.at(from_ptr);
22507
22508 // The move operation is functionally identical to a
22509 // "remove" operation on the "from" location, followed
22510 // immediately by an "add" operation at the target
22511 // location with the value that was just removed.
22512 operation_remove(from_ptr);
22513 operation_add(ptr, v);
22514 break;
22515 }
22516
22517 case patch_operations::copy: {
22518 const auto from_path =
22519 get_value("copy", "from", true).template get<std::string>();
22520 const json_pointer from_ptr(from_path);
22521
22522 // the "from" location must exist - use at()
22523 basic_json const v = result.at(from_ptr);
22524
22525 // The copy is functionally identical to an "add"
22526 // operation at the target location using the value
22527 // specified in the "from" member.
22528 operation_add(ptr, v);
22529 break;
22530 }
22531
22532 case patch_operations::test: {
22533 bool success = false;
22534 JSON_TRY {
22535 // check if "value" matches the one at "path"
22536 // the "path" location must exist - use at()
22537 success = (result.at(ptr) == get_value("test", "value", false));
22538 }
22539 JSON_INTERNAL_CATCH(out_of_range&) {
22540 // ignore out of range errors: success remains false
22541 }
22542
22543 // throw an exception if test fails
22544 if (JSON_HEDLEY_UNLIKELY(!success)) {
22545 JSON_THROW(other_error::create(
22546 501, detail::concat("unsuccessful: ", val.dump()), &val));
22547 }
22548
22549 break;
22550 }
22551
22552 case patch_operations::invalid:
22553 default: {
22554 // op must be "add", "remove", "replace", "move", "copy", or
22555 // "test"
22556 JSON_THROW(parse_error::create(
22557 105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
22558 }
22559 }
22560 }
22561 }
22562
22565 basic_json patch(const basic_json& json_patch) const {
22566 basic_json result = *this;
22567 result.patch_inplace(json_patch);
22568 return result;
22569 }
22570
22573 JSON_HEDLEY_WARN_UNUSED_RESULT
22574 static basic_json diff(const basic_json& source, const basic_json& target,
22575 const std::string& path = "") {
22576 // the patch
22577 basic_json result(value_t::array);
22578
22579 // if the values are the same, return empty patch
22580 if (source == target) {
22581 return result;
22582 }
22583
22584 if (source.type() != target.type()) {
22585 // different types: replace value
22586 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
22587 return result;
22588 }
22589
22590 switch (source.type()) {
22591 case value_t::array: {
22592 // first pass: traverse common elements
22593 std::size_t i = 0;
22594 while (i < source.size() && i < target.size()) {
22595 // recursive call to compare array values at index i
22596 auto temp_diff =
22597 diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
22598 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
22599 ++i;
22600 }
22601
22602 // We now reached the end of at least one array
22603 // in a second pass, traverse the remaining elements
22604
22605 // remove my remaining elements
22606 const auto end_index = static_cast<difference_type>(result.size());
22607 while (i < source.size()) {
22608 // add operations in reverse order to avoid invalid
22609 // indices
22610 result.insert(result.begin() + end_index,
22611 object({{"op", "remove"},
22612 {"path", detail::concat(path, '/', std::to_string(i))}}));
22613 ++i;
22614 }
22615
22616 // add other remaining elements
22617 while (i < target.size()) {
22618 result.push_back({{"op", "add"},
22619 {"path", detail::concat(path, "/-")},
22620 {"value", target[i]}});
22621 ++i;
22622 }
22623
22624 break;
22625 }
22626
22627 case value_t::object: {
22628 // first pass: traverse this object's elements
22629 for (auto it = source.cbegin(); it != source.cend(); ++it) {
22630 // escape the key name to be used in a JSON patch
22631 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
22632
22633 if (target.find(it.key()) != target.end()) {
22634 // recursive call to compare object values at key it
22635 auto temp_diff = diff(it.value(), target[it.key()], path_key);
22636 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
22637 } else {
22638 // found a key that is not in o -> remove it
22639 result.push_back(object({{"op", "remove"}, {"path", path_key}}));
22640 }
22641 }
22642
22643 // second pass: traverse other object's elements
22644 for (auto it = target.cbegin(); it != target.cend(); ++it) {
22645 if (source.find(it.key()) == source.end()) {
22646 // found a key that is not in this -> add it
22647 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
22648 result.push_back(
22649 {{"op", "add"}, {"path", path_key}, {"value", it.value()}});
22650 }
22651 }
22652
22653 break;
22654 }
22655
22656 case value_t::null:
22657 case value_t::string:
22658 case value_t::boolean:
22659 case value_t::number_integer:
22660 case value_t::number_unsigned:
22661 case value_t::number_float:
22662 case value_t::binary:
22663 case value_t::discarded:
22664 default: {
22665 // both primitive type: replace value
22666 result.push_back({{"op", "replace"}, {"path", path}, {"value", target}});
22667 break;
22668 }
22669 }
22670
22671 return result;
22672 }
22674
22676 // JSON Merge Patch functions //
22678
22681
22684 void merge_patch(const basic_json& apply_patch) {
22685 if (apply_patch.is_object()) {
22686 if (!is_object()) {
22687 *this = object();
22688 }
22689 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) {
22690 if (it.value().is_null()) {
22691 erase(it.key());
22692 } else {
22693 operator[](it.key()).merge_patch(it.value());
22694 }
22695 }
22696 } else {
22697 *this = apply_patch;
22698 }
22699 }
22700
22702};
22703
22706NLOHMANN_BASIC_JSON_TPL_DECLARATION
22707std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) {
22708 return j.dump();
22709}
22710
22711inline namespace literals {
22712inline namespace json_literals {
22713
22716JSON_HEDLEY_NON_NULL(1)
22717#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0)
22718inline nlohmann::json operator""_json(const char* s, std::size_t n)
22719#else
22720inline nlohmann::json operator"" _json(const char* s, std::size_t n)
22721#endif
22722{
22723 return nlohmann::json::parse(s, s + n);
22724}
22725
22728JSON_HEDLEY_NON_NULL(1)
22729#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0)
22730inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
22731#else
22732inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
22733#endif
22734{
22735 return nlohmann::json::json_pointer(std::string(s, n));
22736}
22737
22738} // namespace json_literals
22739} // namespace literals
22740NLOHMANN_JSON_NAMESPACE_END
22741
22743// nonmember support //
22745
22746namespace std // NOLINT(cert-dcl58-cpp)
22747{
22748
22751NLOHMANN_BASIC_JSON_TPL_DECLARATION
22752struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
22753{
22754 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const {
22755 return nlohmann::detail::hash(j);
22756 }
22757};
22758
22759// specialization for std::less<value_t>
22760template <>
22761struct less<::nlohmann::detail::value_t> // do not remove the space after '<', see
22762 // https://github.com/nlohmann/json/pull/679
22763{
22768 bool operator()(::nlohmann::detail::value_t lhs,
22769 ::nlohmann::detail::value_t rhs) const noexcept {
22770#if JSON_HAS_THREE_WAY_COMPARISON
22771 return std::is_lt(lhs <=> rhs); // *NOPAD*
22772#else
22773 return ::nlohmann::detail::operator<(lhs, rhs);
22774#endif
22775 }
22776};
22777
22778// C++20 prohibit function specialization in the std namespace.
22779#ifndef JSON_HAS_CPP_20
22780
22783NLOHMANN_BASIC_JSON_TPL_DECLARATION
22784inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1,
22785 nlohmann::NLOHMANN_BASIC_JSON_TPL&
22786 j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name,
22787 // cert-dcl58-cpp)
22788 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::
22789 value && // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22790 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) {
22791 j1.swap(j2);
22792}
22793
22794#endif
22795
22796} // namespace std
22797
22798#if JSON_USE_GLOBAL_UDLS
22799#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0)
22800using nlohmann::literals::json_literals::
22801operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
22802using nlohmann::literals::json_literals::
22803operator""_json_pointer; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
22804#else
22805using nlohmann::literals::json_literals::
22806operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
22807using nlohmann::literals::json_literals::
22808operator"" _json_pointer; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
22809#endif
22810#endif
22811
22812// #include <nlohmann/detail/macro_unscope.hpp>
22813// __ _____ _____ _____
22814// __| | __| | | | JSON for Modern C++
22815// | | |__ | | | | | | version 3.11.3
22816// |_____|_____|_____|_|___| https://github.com/nlohmann/json
22817//
22818// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
22819// SPDX-License-Identifier: MIT
22820
22821// restore clang diagnostic settings
22822#if defined(__clang__)
22823#pragma clang diagnostic pop
22824#endif
22825
22826// clean up
22827#undef JSON_ASSERT
22828#undef JSON_INTERNAL_CATCH
22829#undef JSON_THROW
22830#undef JSON_PRIVATE_UNLESS_TESTED
22831#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
22832#undef NLOHMANN_BASIC_JSON_TPL
22833#undef JSON_EXPLICIT
22834#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
22835#undef JSON_INLINE_VARIABLE
22836#undef JSON_NO_UNIQUE_ADDRESS
22837#undef JSON_DISABLE_ENUM_SERIALIZATION
22838#undef JSON_USE_GLOBAL_UDLS
22839
22840#ifndef JSON_TEST_KEEP_MACROS
22841#undef JSON_CATCH
22842#undef JSON_TRY
22843#undef JSON_HAS_CPP_11
22844#undef JSON_HAS_CPP_14
22845#undef JSON_HAS_CPP_17
22846#undef JSON_HAS_CPP_20
22847#undef JSON_HAS_FILESYSTEM
22848#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
22849#undef JSON_HAS_THREE_WAY_COMPARISON
22850#undef JSON_HAS_RANGES
22851#undef JSON_HAS_STATIC_RTTI
22852#undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22853#endif
22854
22855// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
22856// __ _____ _____ _____
22857// __| | __| | | | JSON for Modern C++
22858// | | |__ | | | | | | version 3.11.3
22859// |_____|_____|_____|_|___| https://github.com/nlohmann/json
22860//
22861// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
22862// SPDX-License-Identifier: MIT
22863
22864#undef JSON_HEDLEY_ALWAYS_INLINE
22865#undef JSON_HEDLEY_ARM_VERSION
22866#undef JSON_HEDLEY_ARM_VERSION_CHECK
22867#undef JSON_HEDLEY_ARRAY_PARAM
22868#undef JSON_HEDLEY_ASSUME
22869#undef JSON_HEDLEY_BEGIN_C_DECLS
22870#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
22871#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
22872#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
22873#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
22874#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
22875#undef JSON_HEDLEY_CLANG_HAS_FEATURE
22876#undef JSON_HEDLEY_CLANG_HAS_WARNING
22877#undef JSON_HEDLEY_COMPCERT_VERSION
22878#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
22879#undef JSON_HEDLEY_CONCAT
22880#undef JSON_HEDLEY_CONCAT3
22881#undef JSON_HEDLEY_CONCAT3_EX
22882#undef JSON_HEDLEY_CONCAT_EX
22883#undef JSON_HEDLEY_CONST
22884#undef JSON_HEDLEY_CONSTEXPR
22885#undef JSON_HEDLEY_CONST_CAST
22886#undef JSON_HEDLEY_CPP_CAST
22887#undef JSON_HEDLEY_CRAY_VERSION
22888#undef JSON_HEDLEY_CRAY_VERSION_CHECK
22889#undef JSON_HEDLEY_C_DECL
22890#undef JSON_HEDLEY_DEPRECATED
22891#undef JSON_HEDLEY_DEPRECATED_FOR
22892#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
22893#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
22894#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
22895#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
22896#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
22897#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
22898#undef JSON_HEDLEY_DIAGNOSTIC_POP
22899#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
22900#undef JSON_HEDLEY_DMC_VERSION
22901#undef JSON_HEDLEY_DMC_VERSION_CHECK
22902#undef JSON_HEDLEY_EMPTY_BASES
22903#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
22904#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
22905#undef JSON_HEDLEY_END_C_DECLS
22906#undef JSON_HEDLEY_FLAGS
22907#undef JSON_HEDLEY_FLAGS_CAST
22908#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
22909#undef JSON_HEDLEY_GCC_HAS_BUILTIN
22910#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
22911#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
22912#undef JSON_HEDLEY_GCC_HAS_EXTENSION
22913#undef JSON_HEDLEY_GCC_HAS_FEATURE
22914#undef JSON_HEDLEY_GCC_HAS_WARNING
22915#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
22916#undef JSON_HEDLEY_GCC_VERSION
22917#undef JSON_HEDLEY_GCC_VERSION_CHECK
22918#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
22919#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
22920#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
22921#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
22922#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
22923#undef JSON_HEDLEY_GNUC_HAS_FEATURE
22924#undef JSON_HEDLEY_GNUC_HAS_WARNING
22925#undef JSON_HEDLEY_GNUC_VERSION
22926#undef JSON_HEDLEY_GNUC_VERSION_CHECK
22927#undef JSON_HEDLEY_HAS_ATTRIBUTE
22928#undef JSON_HEDLEY_HAS_BUILTIN
22929#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
22930#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
22931#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
22932#undef JSON_HEDLEY_HAS_EXTENSION
22933#undef JSON_HEDLEY_HAS_FEATURE
22934#undef JSON_HEDLEY_HAS_WARNING
22935#undef JSON_HEDLEY_IAR_VERSION
22936#undef JSON_HEDLEY_IAR_VERSION_CHECK
22937#undef JSON_HEDLEY_IBM_VERSION
22938#undef JSON_HEDLEY_IBM_VERSION_CHECK
22939#undef JSON_HEDLEY_IMPORT
22940#undef JSON_HEDLEY_INLINE
22941#undef JSON_HEDLEY_INTEL_CL_VERSION
22942#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
22943#undef JSON_HEDLEY_INTEL_VERSION
22944#undef JSON_HEDLEY_INTEL_VERSION_CHECK
22945#undef JSON_HEDLEY_IS_CONSTANT
22946#undef JSON_HEDLEY_IS_CONSTEXPR_
22947#undef JSON_HEDLEY_LIKELY
22948#undef JSON_HEDLEY_MALLOC
22949#undef JSON_HEDLEY_MCST_LCC_VERSION
22950#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
22951#undef JSON_HEDLEY_MESSAGE
22952#undef JSON_HEDLEY_MSVC_VERSION
22953#undef JSON_HEDLEY_MSVC_VERSION_CHECK
22954#undef JSON_HEDLEY_NEVER_INLINE
22955#undef JSON_HEDLEY_NON_NULL
22956#undef JSON_HEDLEY_NO_ESCAPE
22957#undef JSON_HEDLEY_NO_RETURN
22958#undef JSON_HEDLEY_NO_THROW
22959#undef JSON_HEDLEY_NULL
22960#undef JSON_HEDLEY_PELLES_VERSION
22961#undef JSON_HEDLEY_PELLES_VERSION_CHECK
22962#undef JSON_HEDLEY_PGI_VERSION
22963#undef JSON_HEDLEY_PGI_VERSION_CHECK
22964#undef JSON_HEDLEY_PREDICT
22965#undef JSON_HEDLEY_PRINTF_FORMAT
22966#undef JSON_HEDLEY_PRIVATE
22967#undef JSON_HEDLEY_PUBLIC
22968#undef JSON_HEDLEY_PURE
22969#undef JSON_HEDLEY_REINTERPRET_CAST
22970#undef JSON_HEDLEY_REQUIRE
22971#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
22972#undef JSON_HEDLEY_REQUIRE_MSG
22973#undef JSON_HEDLEY_RESTRICT
22974#undef JSON_HEDLEY_RETURNS_NON_NULL
22975#undef JSON_HEDLEY_SENTINEL
22976#undef JSON_HEDLEY_STATIC_ASSERT
22977#undef JSON_HEDLEY_STATIC_CAST
22978#undef JSON_HEDLEY_STRINGIFY
22979#undef JSON_HEDLEY_STRINGIFY_EX
22980#undef JSON_HEDLEY_SUNPRO_VERSION
22981#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
22982#undef JSON_HEDLEY_TINYC_VERSION
22983#undef JSON_HEDLEY_TINYC_VERSION_CHECK
22984#undef JSON_HEDLEY_TI_ARMCL_VERSION
22985#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
22986#undef JSON_HEDLEY_TI_CL2000_VERSION
22987#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
22988#undef JSON_HEDLEY_TI_CL430_VERSION
22989#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
22990#undef JSON_HEDLEY_TI_CL6X_VERSION
22991#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
22992#undef JSON_HEDLEY_TI_CL7X_VERSION
22993#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
22994#undef JSON_HEDLEY_TI_CLPRU_VERSION
22995#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
22996#undef JSON_HEDLEY_TI_VERSION
22997#undef JSON_HEDLEY_TI_VERSION_CHECK
22998#undef JSON_HEDLEY_UNAVAILABLE
22999#undef JSON_HEDLEY_UNLIKELY
23000#undef JSON_HEDLEY_UNPREDICTABLE
23001#undef JSON_HEDLEY_UNREACHABLE
23002#undef JSON_HEDLEY_UNREACHABLE_RETURN
23003#undef JSON_HEDLEY_VERSION
23004#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
23005#undef JSON_HEDLEY_VERSION_DECODE_MINOR
23006#undef JSON_HEDLEY_VERSION_DECODE_REVISION
23007#undef JSON_HEDLEY_VERSION_ENCODE
23008#undef JSON_HEDLEY_WARNING
23009#undef JSON_HEDLEY_WARN_UNUSED_RESULT
23010#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
23011#undef JSON_HEDLEY_FALL_THROUGH
23012
23013#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:18132
constexpr bool is_string() const noexcept
Definition json.hpp:19279
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:20446
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:18196
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:20038
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:22024
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:21965
reference back()
access the last element
Definition json.hpp:20263
basic_json value_type
Definition json.hpp:18231
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:18798
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
Definition json.hpp:21834
const_reference front() const
access the first element
Definition json.hpp:20259
constexpr bool is_array() const noexcept
Definition json.hpp:19275
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
Definition json.hpp:21199
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:20210
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:20555
iter_impl< const basic_json > const_iterator
Definition json.hpp:18254
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:21981
constexpr bool is_number_integer() const noexcept
Definition json.hpp:19252
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:18258
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:21974
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:18249
std::size_t size_type
Definition json.hpp:18241
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:19236
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:20062
detail::error_handler_t error_handler_t
Definition json.hpp:18194
const value_type & const_reference
Definition json.hpp:18236
void swap(binary_t &other)
exchanges the values
Definition json.hpp:21274
ReferenceType get_ref()
Definition json.hpp:19712
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:21150
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:19724
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:19287
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 >{}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 >{}))
Definition json.hpp:19624
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:20960
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer< basic_json::string_t >) ValueType value(const
access the first element
Definition json.hpp:20231
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:20010
const_reference back() const
access the last element
Definition json.hpp:20271
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:20350
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:20913
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:21215
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:18935
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:21061
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:18264
nlohmann::byte_container_with_subtype< std::vector< std::uint8_t > > binary_t
Definition json.hpp:18382
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:19877
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:19259
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:21157
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:21988
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:20948
detail::parser_callback_t< basic_json > parser_callback_t
Definition json.hpp:18770
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:18974
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:21936
detail::parse_event_t parse_event_t
Definition json.hpp:18766
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:20115
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:18946
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:18787
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:22010
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:20457
std::vector< basic_json, std::allocator< basic_json > > array_t
Definition json.hpp:18358
const binary_t & get_binary() const
get a binary value
Definition json.hpp:19796
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:21080
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:20166
value_type & reference
Definition json.hpp:18234
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:18198
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:20571
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:21910
nlohmann::ordered_map< std::string, basic_json, default_object_comparator_t, std::allocator< std::pair< const std::string, basic_json > > > object_t
Definition json.hpp:18353
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:22002
iterator find(const typename object_t::key_type &key)
Definition json.hpp:20491
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:18925
JSON_HEDLEY_NON_NULL(2) static bool sax_parse(detail
Definition json.hpp:21795
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:19915
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:18269
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:18980
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:20503
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:21902
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:20284
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:21038
double number_float_t
Definition json.hpp:18378
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:20092
std::allocator< basic_json > allocator_type
Definition json.hpp:18244
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:18247
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:19209
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:19678
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:19817
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:20518
constexpr bool is_number_float() const noexcept
Definition json.hpp:19265
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:21942
bool boolean_t
Definition json.hpp:18366
std::less< std::string > default_object_comparator_t
Definition json.hpp:18348
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:20941
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:19989
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:19441
~basic_json() noexcept
destructor
Definition json.hpp:19194
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:18873
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:21290
binary_t & get_binary()
get a binary value
Definition json.hpp:19785
constexpr bool is_number() const noexcept
Definition json.hpp:19248
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:21126
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:19667
reference operator[](size_type idx)
access specified array element
Definition json.hpp:19933
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:19173
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:21958
std::int64_t number_integer_t
Definition json.hpp:18370
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:19428
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:19895
constexpr bool is_binary() const noexcept
Definition json.hpp:19283
void swap(object_t &other)
exchanges the values
Definition json.hpp:21242
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:21108
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:18956
void swap(array_t &other)
exchanges the values
Definition json.hpp:21226
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:20463
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:20884
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:20579
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:19226
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:20967
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:20188
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:18967
std::string string_t
Definition json.hpp:18362
void push_back(const basic_json &val)
Definition json.hpp:20891
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:20140
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:19857
json_value m_value
the value of the current element
Definition json.hpp:21868
json_sax< basic_json > json_sax_t
Definition json.hpp:18202
constexpr bool is_boolean() const noexcept
Definition json.hpp:19244
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:20545
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:19230
constexpr bool is_null() const noexcept
Definition json.hpp:19240
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:21951
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:19157
iter_impl< basic_json > iterator
Definition json.hpp:18252
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:18783
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:19976
std::ptrdiff_t difference_type
Definition json.hpp:18239
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:21057
std::uint64_t number_unsigned_t
Definition json.hpp:18374
friend std::istream & operator>>(std::istream &i, basic_json &j)
Definition json.hpp:21820
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:21922
void swap(string_t &other)
exchanges the values
Definition json.hpp:21258
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:18813
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:18256
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:19837
detail::actual_object_comparator_t< basic_json > object_comparator_t
Definition json.hpp:18386
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:19099
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:20920
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:20989
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:21916
constexpr bool is_object() const noexcept
Definition json.hpp:19271
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:21930
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:21018
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:18992
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:20562
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:21996
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:20533
::nlohmann::json_pointer< std::string > json_pointer
Definition json.hpp:18191
an internal type for a backed binary type
Definition json.hpp:5770
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:5777
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5797
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5786
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:5817
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:5791
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:5823
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:5781
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:5810
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:5828
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:8752
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:8768
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:8792
void write_bson(const BasicJsonType &j)
Definition json.hpp:14273
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:14265
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
Definition json.hpp:14820
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:14551
void write_cbor(const BasicJsonType &j)
Definition json.hpp:14302
general exception of the basic_json class
Definition json.hpp:4369
const int id
the id of the exception
Definition json.hpp:4375
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4372
Definition json.hpp:6061
exception indicating errors with iterators
Definition json.hpp:4506
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:12872
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:12479
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:12826
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:12470
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:12780
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:12814
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:12866
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:12696
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:12965
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:12639
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:12832
reference operator[](difference_type n) const
access to successor
Definition json.hpp:12930
pointer operator->() const
dereference the iterator
Definition json.hpp:12603
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:12902
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:12377
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:12882
reference value() const
return the value of an iterator
Definition json.hpp:12980
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:12820
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
Definition json.hpp:12384
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:12650
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:12565
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:12892
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
Definition json.hpp:12388
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:12457
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:12685
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:12448
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:12531
Definition json.hpp:5118
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5181
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5184
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5165
const iteration_proxy_value & operator*() const
dereference operator (needed for range-based for)
Definition json.hpp:5162
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5219
const string_type & key() const
return key of the iterator
Definition json.hpp:5187
proxy class for the items() function
Definition json.hpp:5223
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5246
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5241
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5232
Definition json.hpp:6106
Definition json.hpp:14050
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:13050
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:13061
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:13056
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:13072
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13092
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:13095
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:13087
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:13040
reference value() const
return the value of an iterator
Definition json.hpp:13101
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:13047
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:13067
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:13038
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13082
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:13043
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:13077
Definition json.hpp:7015
Definition json.hpp:6740
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:6579
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:6592
Definition json.hpp:7090
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7120
token_type
token types for the parser
Definition json.hpp:7093
@ value_float
Definition json.hpp:7103
@ begin_array
the character for array begin [
Definition json.hpp:7105
@ value_string
a string – use get_string() for actual value
Definition json.hpp:7098
@ end_array
the character for array end ]
Definition json.hpp:7107
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:7094
@ parse_error
indicating a parse error
Definition json.hpp:7111
@ value_integer
Definition json.hpp:7101
@ value_separator
the value separator ,
Definition json.hpp:7110
@ end_object
the character for object end }
Definition json.hpp:7108
@ literal_true
the true literal
Definition json.hpp:7095
@ begin_object
the character for object begin {
Definition json.hpp:7106
@ value_unsigned
Definition json.hpp:7099
@ literal_null
the null literal
Definition json.hpp:7097
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:7112
@ name_separator
the name separator :
Definition json.hpp:7109
@ literal_or_value
Definition json.hpp:7113
@ literal_false
the false literal
Definition json.hpp:7096
lexical analysis
Definition json.hpp:7167
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8424
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8414
std::string get_token_string() const
Definition json.hpp:8391
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8369
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8386
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8372
string_t & get_string()
Definition json.hpp:8379
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8375
exception indicating other library errors
Definition json.hpp:4557
exception indicating access out of the defined range
Definition json.hpp:4540
Definition json.hpp:14219
output adapter for output streams
Definition json.hpp:14187
output adapter for basic_string
Definition json.hpp:14205
output adapter for byte vectors
Definition json.hpp:14169
exception indicating a parse error
Definition json.hpp:4451
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4464
const std::size_t byte
byte index of the parse error
Definition json.hpp:4492
parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition json.hpp:11740
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:11758
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:11810
Definition json.hpp:12186
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:12206
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:12203
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:12209
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:12200
Definition json.hpp:16876
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:17760
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:16891
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:17755
const char decimal_point
the locale's decimal point character
Definition json.hpp:17757
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:17768
string_t indent_string
the indentation string
Definition json.hpp:17765
const std::lconv * loc
the locale
Definition json.hpp:17753
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:17750
const char indent_char
the indentation character
Definition json.hpp:17763
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:16931
exception indicating executing a member function with a wrong type
Definition json.hpp:4523
Definition json.hpp:6243
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:13184
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:13260
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:13269
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:13983
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:13206
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:13315
void pop_back()
remove last reference token
Definition json.hpp:13287
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:13210
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:13248
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13311
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.hpp:14023
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:13233
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:13253
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:13275
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:13241
const string_t & back() const
return last reference token
Definition json.hpp:13297
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:14003
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:13225
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13307
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:15851
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:16248
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:16126
boundaries compute_boundaries(FloatType value)
Definition json.hpp:15987
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:16572
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:16330
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:16674
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:16717
detail namespace with internal helper functions
Definition json.hpp:224
input_format_t
the supported input formats
Definition json.hpp:6018
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:16795
parse_event_t
Definition json.hpp:11706
@ value
the parser finished reading a JSON value
Definition json.hpp:11718
@ key
the parser read a key of a value in an object
Definition json.hpp:11716
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:11714
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:11712
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:11708
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:11710
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:14165
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3158
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:8726
@ ignore
ignore tags
Definition json.hpp:8728
@ store
store tags as binary type
Definition json.hpp:8729
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:8727
value_t
the JSON type enumeration
Definition json.hpp:3067
@ null
null value
Definition json.hpp:3068
@ number_integer
number value (signed integer)
Definition json.hpp:3073
@ boolean
boolean value
Definition json.hpp:3072
@ discarded
discarded by the parser callback function
Definition json.hpp:3077
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3076
@ object
object (unordered set of name/value pairs)
Definition json.hpp:3069
@ string
string value
Definition json.hpp:3071
@ number_float
number value (floating-point)
Definition json.hpp:3075
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3074
@ array
array (ordered collection of values)
Definition json.hpp:3070
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:5883
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3097
error_handler_t
how to treat decoding errors
Definition json.hpp:16870
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:16871
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:16872
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3175
namespace for Niels Lohmann
Definition json.hpp:5718
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:5742
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType >{}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType >{}))
convert a JSON value to any value type
Definition json.hpp:5731
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:5722
Definition json.hpp:3689
Definition json.hpp:3705
Definition json.hpp:3738
Definition json.hpp:248
Definition json.hpp:15975
Definition json.hpp:16113
Definition json.hpp:15862
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:15885
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:15965
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:15950
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:15874
Definition json.hpp:5328
Definition json.hpp:5041
Definition json.hpp:3636
Definition json.hpp:3686
Definition json.hpp:3659
Definition json.hpp:3673
Definition json.hpp:4594
Definition json.hpp:3292
an iterator value
Definition json.hpp:12278
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:12282
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:12284
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:12280
Definition json.hpp:3595
Definition json.hpp:3582
Definition json.hpp:4194
Definition json.hpp:4022
Definition json.hpp:3920
Definition json.hpp:3981
Definition json.hpp:3851
Definition json.hpp:3880
Definition json.hpp:3984
Definition json.hpp:3993
Definition json.hpp:3827
Definition json.hpp:3959
Definition json.hpp:3878
Definition json.hpp:3886
Definition json.hpp:3995
Definition json.hpp:3770
Definition json.hpp:3751
Definition json.hpp:263
Definition json.hpp:3643
Definition json.hpp:6291
Definition json.hpp:3786
Definition json.hpp:4001
Definition json.hpp:3603
Definition json.hpp:4079
Definition json.hpp:4076
Definition json.hpp:3799
Definition json.hpp:8666
Definition json.hpp:8637
Definition json.hpp:4012
Definition json.hpp:4211
Definition json.hpp:3430
Definition json.hpp:3414
Default base class of the basic_json class.
Definition json.hpp:13138
Definition json.hpp:226
Definition json.hpp:3745
Definition json.hpp:238
struct to capture the start position of the current token
Definition json.hpp:3213
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3217
std::size_t lines_read
the number of lines read
Definition json.hpp:3219
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3215
Definition json.hpp:3359
Definition json.hpp:3363
Definition json.hpp:5688
Definition json.hpp:3306
Definition json.hpp:3321
Definition json.hpp:4160
Definition json.hpp:4122
Definition json.hpp:6132
SAX interface.
Definition json.hpp:6453
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:17806
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:22768