1 // __ _____ _____ _____
2 // __| | __| | | | JSON for Modern C++
3 // | | |__ | | | | | | version 3.11.2
4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
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 \****************************************************************************/
18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
19 #define INCLUDE_NLOHMANN_JSON_HPP_
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
26 #include <iosfwd> // istream, ostream
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
34 // #include <nlohmann/adl_serializer.hpp>
35 // __ _____ _____ _____
36 // __| | __| | | | JSON for Modern C++
37 // | | |__ | | | | | | version 3.11.2
38 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
40 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
41 // SPDX-License-Identifier: MIT
47 // #include <nlohmann/detail/abi_macros.hpp>
48 // __ _____ _____ _____
49 // __| | __| | | | JSON for Modern C++
50 // | | |__ | | | | | | version 3.11.2
51 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
53 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
54 // SPDX-License-Identifier: MIT
58 // This file contains all macro definitions affecting or depending on the ABI
60 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
63 #warning "Already included a different version of the library!"
68 #define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69 #define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70 #define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
72 #ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
76 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
86 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
92 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
96 // Construct the namespace ABI tags component
97 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
101 #define NLOHMANN_JSON_ABI_TAGS \
102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
106 // Construct the namespace version component
107 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
108 _v ## major ## _ ## minor ## _ ## patch
109 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
112 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113 #define NLOHMANN_JSON_NAMESPACE_VERSION
115 #define NLOHMANN_JSON_NAMESPACE_VERSION \
116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
117 NLOHMANN_JSON_VERSION_MINOR, \
118 NLOHMANN_JSON_VERSION_PATCH)
121 // Combine namespace components
122 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
126 #ifndef NLOHMANN_JSON_NAMESPACE
127 #define NLOHMANN_JSON_NAMESPACE \
128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
129 NLOHMANN_JSON_ABI_TAGS, \
130 NLOHMANN_JSON_NAMESPACE_VERSION)
133 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134 #define NLOHMANN_JSON_NAMESPACE_BEGIN \
137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
138 NLOHMANN_JSON_ABI_TAGS, \
139 NLOHMANN_JSON_NAMESPACE_VERSION) \
143 #ifndef NLOHMANN_JSON_NAMESPACE_END
144 #define NLOHMANN_JSON_NAMESPACE_END \
145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
146 } // namespace nlohmann
149 // #include <nlohmann/detail/conversions/from_json.hpp>
150 // __ _____ _____ _____
151 // __| | __| | | | JSON for Modern C++
152 // | | |__ | | | | | | version 3.11.2
153 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
155 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
156 // SPDX-License-Identifier: MIT
160 #include <algorithm> // transform
161 #include <array> // array
162 #include <forward_list> // forward_list
163 #include <iterator> // inserter, front_inserter, end
164 #include <map> // map
165 #include <string> // string
166 #include <tuple> // tuple, make_tuple
167 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
168 #include <unordered_map> // unordered_map
169 #include <utility> // pair, declval
170 #include <valarray> // valarray
172 // #include <nlohmann/detail/exceptions.hpp>
173 // __ _____ _____ _____
174 // __| | __| | | | JSON for Modern C++
175 // | | |__ | | | | | | version 3.11.2
176 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
178 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
179 // SPDX-License-Identifier: MIT
183 #include <cstddef> // nullptr_t
184 #include <exception> // exception
186 #include <numeric> // accumulate
188 #include <stdexcept> // runtime_error
189 #include <string> // to_string
190 #include <vector> // vector
192 // #include <nlohmann/detail/value_t.hpp>
193 // __ _____ _____ _____
194 // __| | __| | | | JSON for Modern C++
195 // | | |__ | | | | | | version 3.11.2
196 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
198 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
199 // SPDX-License-Identifier: MIT
203 #include <array> // array
204 #include <cstddef> // size_t
205 #include <cstdint> // uint8_t
206 #include <string> // string
208 // #include <nlohmann/detail/macro_scope.hpp>
209 // __ _____ _____ _____
210 // __| | __| | | | JSON for Modern C++
211 // | | |__ | | | | | | version 3.11.2
212 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
214 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
215 // SPDX-License-Identifier: MIT
219 #include <utility> // declval, pair
220 // #include <nlohmann/detail/meta/detected.hpp>
221 // __ _____ _____ _____
222 // __| | __| | | | JSON for Modern C++
223 // | | |__ | | | | | | version 3.11.2
224 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
226 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
227 // SPDX-License-Identifier: MIT
231 #include <type_traits>
233 // #include <nlohmann/detail/meta/void_t.hpp>
234 // __ _____ _____ _____
235 // __| | __| | | | JSON for Modern C++
236 // | | |__ | | | | | | version 3.11.2
237 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
240 // SPDX-License-Identifier: MIT
244 // #include <nlohmann/detail/abi_macros.hpp>
247 NLOHMANN_JSON_NAMESPACE_BEGIN
251 template<typename ...Ts> struct make_void
255 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
257 } // namespace detail
258 NLOHMANN_JSON_NAMESPACE_END
261 NLOHMANN_JSON_NAMESPACE_BEGIN
265 // https://en.cppreference.com/w/cpp/experimental/is_detected
269 ~nonesuch() = delete;
270 nonesuch(nonesuch const&) = delete;
271 nonesuch(nonesuch const&&) = delete;
272 void operator=(nonesuch const&) = delete;
273 void operator=(nonesuch&&) = delete;
276 template<class Default,
278 template<class...> class Op,
282 using value_t = std::false_type;
283 using type = Default;
286 template<class Default, template<class...> class Op, class... Args>
287 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
289 using value_t = std::true_type;
290 using type = Op<Args...>;
293 template<template<class...> class Op, class... Args>
294 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
296 template<template<class...> class Op, class... Args>
297 struct is_detected_lazy : is_detected<Op, Args...> { };
299 template<template<class...> class Op, class... Args>
300 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
302 template<class Default, template<class...> class Op, class... Args>
303 using detected_or = detector<Default, void, Op, Args...>;
305 template<class Default, template<class...> class Op, class... Args>
306 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
308 template<class Expected, template<class...> class Op, class... Args>
309 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
311 template<class To, template<class...> class Op, class... Args>
312 using is_detected_convertible =
313 std::is_convertible<detected_t<Op, Args...>, To>;
315 } // namespace detail
316 NLOHMANN_JSON_NAMESPACE_END
318 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
321 // __ _____ _____ _____
322 // __| | __| | | | JSON for Modern C++
323 // | | |__ | | | | | | version 3.11.2
324 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
326 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
327 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
328 // SPDX-License-Identifier: MIT
330 /* Hedley - https://nemequ.github.io/hedley
331 * Created by Evan Nemerson <evan@nemerson.com>
334 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
335 #if defined(JSON_HEDLEY_VERSION)
336 #undef JSON_HEDLEY_VERSION
338 #define JSON_HEDLEY_VERSION 15
340 #if defined(JSON_HEDLEY_STRINGIFY_EX)
341 #undef JSON_HEDLEY_STRINGIFY_EX
343 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
345 #if defined(JSON_HEDLEY_STRINGIFY)
346 #undef JSON_HEDLEY_STRINGIFY
348 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
350 #if defined(JSON_HEDLEY_CONCAT_EX)
351 #undef JSON_HEDLEY_CONCAT_EX
353 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
355 #if defined(JSON_HEDLEY_CONCAT)
356 #undef JSON_HEDLEY_CONCAT
358 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
360 #if defined(JSON_HEDLEY_CONCAT3_EX)
361 #undef JSON_HEDLEY_CONCAT3_EX
363 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
365 #if defined(JSON_HEDLEY_CONCAT3)
366 #undef JSON_HEDLEY_CONCAT3
368 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
370 #if defined(JSON_HEDLEY_VERSION_ENCODE)
371 #undef JSON_HEDLEY_VERSION_ENCODE
373 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
375 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
376 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
378 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
380 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
381 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
383 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
385 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
386 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
388 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
390 #if defined(JSON_HEDLEY_GNUC_VERSION)
391 #undef JSON_HEDLEY_GNUC_VERSION
393 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
394 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
395 #elif defined(__GNUC__)
396 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
399 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
400 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
402 #if defined(JSON_HEDLEY_GNUC_VERSION)
403 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
405 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
408 #if defined(JSON_HEDLEY_MSVC_VERSION)
409 #undef JSON_HEDLEY_MSVC_VERSION
411 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
412 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
413 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
414 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
415 #elif defined(_MSC_VER) && !defined(__ICL)
416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
419 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
420 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
422 #if !defined(JSON_HEDLEY_MSVC_VERSION)
423 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
424 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
425 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
426 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
432 #if defined(JSON_HEDLEY_INTEL_VERSION)
433 #undef JSON_HEDLEY_INTEL_VERSION
435 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
436 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
437 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
438 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
441 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
442 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
444 #if defined(JSON_HEDLEY_INTEL_VERSION)
445 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
447 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
450 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
451 #undef JSON_HEDLEY_INTEL_CL_VERSION
453 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
454 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
457 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
458 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
460 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
461 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
463 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
466 #if defined(JSON_HEDLEY_PGI_VERSION)
467 #undef JSON_HEDLEY_PGI_VERSION
469 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
470 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
473 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
474 #undef JSON_HEDLEY_PGI_VERSION_CHECK
476 #if defined(JSON_HEDLEY_PGI_VERSION)
477 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
479 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
482 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
483 #undef JSON_HEDLEY_SUNPRO_VERSION
485 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
486 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
487 #elif defined(__SUNPRO_C)
488 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
489 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
490 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
491 #elif defined(__SUNPRO_CC)
492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
495 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
496 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
498 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
499 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
501 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
504 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
505 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
507 #if defined(__EMSCRIPTEN__)
508 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
511 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
512 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
514 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
515 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
517 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
520 #if defined(JSON_HEDLEY_ARM_VERSION)
521 #undef JSON_HEDLEY_ARM_VERSION
523 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
524 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
525 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
526 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
529 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
530 #undef JSON_HEDLEY_ARM_VERSION_CHECK
532 #if defined(JSON_HEDLEY_ARM_VERSION)
533 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
535 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
538 #if defined(JSON_HEDLEY_IBM_VERSION)
539 #undef JSON_HEDLEY_IBM_VERSION
541 #if defined(__ibmxl__)
542 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
543 #elif defined(__xlC__) && defined(__xlC_ver__)
544 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
545 #elif defined(__xlC__)
546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
549 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
550 #undef JSON_HEDLEY_IBM_VERSION_CHECK
552 #if defined(JSON_HEDLEY_IBM_VERSION)
553 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
555 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
558 #if defined(JSON_HEDLEY_TI_VERSION)
559 #undef JSON_HEDLEY_TI_VERSION
562 defined(__TI_COMPILER_VERSION__) && \
564 defined(__TMS470__) || defined(__TI_ARM__) || \
565 defined(__MSP430__) || \
566 defined(__TMS320C2000__) \
568 #if (__TI_COMPILER_VERSION__ >= 16000000)
569 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
573 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
574 #undef JSON_HEDLEY_TI_VERSION_CHECK
576 #if defined(JSON_HEDLEY_TI_VERSION)
577 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
579 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
582 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
583 #undef JSON_HEDLEY_TI_CL2000_VERSION
585 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
586 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
589 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
590 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
592 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
593 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
595 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
598 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
599 #undef JSON_HEDLEY_TI_CL430_VERSION
601 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
602 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
605 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
606 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
608 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
609 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
611 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
614 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
615 #undef JSON_HEDLEY_TI_ARMCL_VERSION
617 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
618 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
621 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
622 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
624 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
625 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
627 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
630 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
631 #undef JSON_HEDLEY_TI_CL6X_VERSION
633 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
634 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
637 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
638 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
640 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
641 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
643 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
646 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
647 #undef JSON_HEDLEY_TI_CL7X_VERSION
649 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
650 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
653 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
654 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
656 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
657 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
659 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
662 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
663 #undef JSON_HEDLEY_TI_CLPRU_VERSION
665 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
666 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
669 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
670 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
672 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
673 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
675 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
678 #if defined(JSON_HEDLEY_CRAY_VERSION)
679 #undef JSON_HEDLEY_CRAY_VERSION
682 #if defined(_RELEASE_PATCHLEVEL)
683 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
685 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
689 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
690 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
692 #if defined(JSON_HEDLEY_CRAY_VERSION)
693 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
695 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
698 #if defined(JSON_HEDLEY_IAR_VERSION)
699 #undef JSON_HEDLEY_IAR_VERSION
701 #if defined(__IAR_SYSTEMS_ICC__)
703 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
705 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
709 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
710 #undef JSON_HEDLEY_IAR_VERSION_CHECK
712 #if defined(JSON_HEDLEY_IAR_VERSION)
713 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
715 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
718 #if defined(JSON_HEDLEY_TINYC_VERSION)
719 #undef JSON_HEDLEY_TINYC_VERSION
721 #if defined(__TINYC__)
722 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
725 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
726 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
728 #if defined(JSON_HEDLEY_TINYC_VERSION)
729 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
731 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
734 #if defined(JSON_HEDLEY_DMC_VERSION)
735 #undef JSON_HEDLEY_DMC_VERSION
738 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
741 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
742 #undef JSON_HEDLEY_DMC_VERSION_CHECK
744 #if defined(JSON_HEDLEY_DMC_VERSION)
745 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
747 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
750 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
751 #undef JSON_HEDLEY_COMPCERT_VERSION
753 #if defined(__COMPCERT_VERSION__)
754 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
757 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
758 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
760 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
761 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
763 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
766 #if defined(JSON_HEDLEY_PELLES_VERSION)
767 #undef JSON_HEDLEY_PELLES_VERSION
769 #if defined(__POCC__)
770 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
773 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
774 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
776 #if defined(JSON_HEDLEY_PELLES_VERSION)
777 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
779 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
782 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
783 #undef JSON_HEDLEY_MCST_LCC_VERSION
785 #if defined(__LCC__) && defined(__LCC_MINOR__)
786 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
789 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
790 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
792 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
793 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
795 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
798 #if defined(JSON_HEDLEY_GCC_VERSION)
799 #undef JSON_HEDLEY_GCC_VERSION
802 defined(JSON_HEDLEY_GNUC_VERSION) && \
803 !defined(__clang__) && \
804 !defined(JSON_HEDLEY_INTEL_VERSION) && \
805 !defined(JSON_HEDLEY_PGI_VERSION) && \
806 !defined(JSON_HEDLEY_ARM_VERSION) && \
807 !defined(JSON_HEDLEY_CRAY_VERSION) && \
808 !defined(JSON_HEDLEY_TI_VERSION) && \
809 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
810 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
811 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
812 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
813 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
814 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
815 !defined(__COMPCERT__) && \
816 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
817 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
820 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
821 #undef JSON_HEDLEY_GCC_VERSION_CHECK
823 #if defined(JSON_HEDLEY_GCC_VERSION)
824 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
826 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
829 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
830 #undef JSON_HEDLEY_HAS_ATTRIBUTE
833 defined(__has_attribute) && \
835 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
837 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
839 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
842 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
843 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
845 #if defined(__has_attribute)
846 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
848 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
851 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
852 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
854 #if defined(__has_attribute)
855 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
857 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
860 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
861 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
864 defined(__has_cpp_attribute) && \
865 defined(__cplusplus) && \
866 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
867 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
869 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
872 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
873 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
875 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
876 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
878 !defined(JSON_HEDLEY_PGI_VERSION) && \
879 !defined(JSON_HEDLEY_IAR_VERSION) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
881 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
882 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
884 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
887 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
888 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
890 #if defined(__has_cpp_attribute) && defined(__cplusplus)
891 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
893 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
896 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
897 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
899 #if defined(__has_cpp_attribute) && defined(__cplusplus)
900 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
902 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
905 #if defined(JSON_HEDLEY_HAS_BUILTIN)
906 #undef JSON_HEDLEY_HAS_BUILTIN
908 #if defined(__has_builtin)
909 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
911 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
914 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
915 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
917 #if defined(__has_builtin)
918 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
920 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
923 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
924 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
926 #if defined(__has_builtin)
927 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
929 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
932 #if defined(JSON_HEDLEY_HAS_FEATURE)
933 #undef JSON_HEDLEY_HAS_FEATURE
935 #if defined(__has_feature)
936 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
938 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
941 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
942 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
944 #if defined(__has_feature)
945 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
947 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
950 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
951 #undef JSON_HEDLEY_GCC_HAS_FEATURE
953 #if defined(__has_feature)
954 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
956 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
959 #if defined(JSON_HEDLEY_HAS_EXTENSION)
960 #undef JSON_HEDLEY_HAS_EXTENSION
962 #if defined(__has_extension)
963 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
965 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
968 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
969 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
971 #if defined(__has_extension)
972 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
974 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
977 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
978 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
980 #if defined(__has_extension)
981 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
983 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
986 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
987 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
989 #if defined(__has_declspec_attribute)
990 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
992 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
995 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
996 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
998 #if defined(__has_declspec_attribute)
999 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1001 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1004 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1005 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1007 #if defined(__has_declspec_attribute)
1008 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1010 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1013 #if defined(JSON_HEDLEY_HAS_WARNING)
1014 #undef JSON_HEDLEY_HAS_WARNING
1016 #if defined(__has_warning)
1017 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1019 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1022 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1023 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1025 #if defined(__has_warning)
1026 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1028 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1031 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1032 #undef JSON_HEDLEY_GCC_HAS_WARNING
1034 #if defined(__has_warning)
1035 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1037 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1041 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1042 defined(__clang__) || \
1043 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1044 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1045 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1046 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1047 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1048 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1049 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1050 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1051 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1052 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1053 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1054 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1055 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1056 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1057 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1058 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1059 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1060 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1061 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1063 #define JSON_HEDLEY_PRAGMA(value)
1066 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1067 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1069 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1070 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1072 #if defined(__clang__)
1073 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1074 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1075 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1076 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1077 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1078 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1079 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1080 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1082 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1083 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1086 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1090 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1091 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1092 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1094 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1095 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1097 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1098 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1102 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1103 #define JSON_HEDLEY_DIAGNOSTIC_POP
1106 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1107 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1108 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1109 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1111 #if defined(__cplusplus)
1112 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1113 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1114 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1115 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1116 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1117 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1118 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1119 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1121 JSON_HEDLEY_DIAGNOSTIC_POP
1123 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1124 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1125 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1126 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1128 JSON_HEDLEY_DIAGNOSTIC_POP
1131 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1139 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1140 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1143 #if defined(JSON_HEDLEY_CONST_CAST)
1144 #undef JSON_HEDLEY_CONST_CAST
1146 #if defined(__cplusplus)
1147 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1149 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1150 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1151 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1152 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1154 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1156 JSON_HEDLEY_DIAGNOSTIC_POP \
1159 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1162 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1163 #undef JSON_HEDLEY_REINTERPRET_CAST
1165 #if defined(__cplusplus)
1166 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1168 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1171 #if defined(JSON_HEDLEY_STATIC_CAST)
1172 #undef JSON_HEDLEY_STATIC_CAST
1174 #if defined(__cplusplus)
1175 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1177 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1180 #if defined(JSON_HEDLEY_CPP_CAST)
1181 #undef JSON_HEDLEY_CPP_CAST
1183 #if defined(__cplusplus)
1184 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1185 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1186 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1187 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1189 JSON_HEDLEY_DIAGNOSTIC_POP
1190 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1191 # define JSON_HEDLEY_CPP_CAST(T, expr) \
1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1193 _Pragma("diag_suppress=Pe137") \
1194 JSON_HEDLEY_DIAGNOSTIC_POP
1196 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1199 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1202 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1203 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1205 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1206 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1207 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1208 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1209 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1211 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1213 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1215 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1217 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1219 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1222 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1223 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1224 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1225 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1226 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1227 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1229 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1231 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1232 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1234 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1236 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1238 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1240 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1246 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1247 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1249 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1251 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1253 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1255 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1257 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1259 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1262 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1263 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1264 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1265 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1267 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1269 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1271 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1277 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1278 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1280 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1282 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1284 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1286 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1288 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1290 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1292 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1294 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1297 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1298 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1299 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1301 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1303 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1309 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1310 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1312 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1314 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1316 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1322 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1323 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1325 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1327 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1329 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1337 #if defined(JSON_HEDLEY_DEPRECATED)
1338 #undef JSON_HEDLEY_DEPRECATED
1340 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1341 #undef JSON_HEDLEY_DEPRECATED_FOR
1344 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1345 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1346 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1347 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1349 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1350 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1351 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1352 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1353 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1354 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1355 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1356 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1357 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1358 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1359 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1360 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1361 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1362 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1363 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1364 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1365 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1367 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1369 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1370 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1371 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1373 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1374 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1375 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1377 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1379 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1380 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1381 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1382 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1383 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1384 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1386 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1387 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1388 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1389 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1390 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1391 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1392 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1393 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1395 #define JSON_HEDLEY_DEPRECATED(since)
1396 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1399 #if defined(JSON_HEDLEY_UNAVAILABLE)
1400 #undef JSON_HEDLEY_UNAVAILABLE
1403 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1404 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1405 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1406 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1407 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1409 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1412 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1413 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1415 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1416 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1419 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1420 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1422 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1423 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1425 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1426 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1427 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1429 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1431 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1432 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1433 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1434 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1435 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1436 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1437 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1438 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1439 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1441 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1442 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444 #elif defined(_Check_return_) /* SAL */
1445 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1452 #if defined(JSON_HEDLEY_SENTINEL)
1453 #undef JSON_HEDLEY_SENTINEL
1456 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1457 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1458 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1459 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1460 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1461 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1463 #define JSON_HEDLEY_SENTINEL(position)
1466 #if defined(JSON_HEDLEY_NO_RETURN)
1467 #undef JSON_HEDLEY_NO_RETURN
1469 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1470 #define JSON_HEDLEY_NO_RETURN __noreturn
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1474 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1475 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1476 #define JSON_HEDLEY_NO_RETURN _Noreturn
1477 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1478 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1480 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1481 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1482 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1483 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1484 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1485 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1486 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1488 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1490 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1492 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1494 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1495 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1496 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1497 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1498 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1499 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1501 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1502 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1503 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1504 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1505 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1506 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1507 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1508 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1509 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1511 #define JSON_HEDLEY_NO_RETURN
1514 #if defined(JSON_HEDLEY_NO_ESCAPE)
1515 #undef JSON_HEDLEY_NO_ESCAPE
1517 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1518 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1520 #define JSON_HEDLEY_NO_ESCAPE
1523 #if defined(JSON_HEDLEY_UNREACHABLE)
1524 #undef JSON_HEDLEY_UNREACHABLE
1526 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1527 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1529 #if defined(JSON_HEDLEY_ASSUME)
1530 #undef JSON_HEDLEY_ASSUME
1533 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1534 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1535 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1536 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1537 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1538 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1540 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1541 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1542 #if defined(__cplusplus)
1543 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1545 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1549 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1550 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1551 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1552 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1553 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1557 #elif defined(JSON_HEDLEY_ASSUME)
1558 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1560 #if !defined(JSON_HEDLEY_ASSUME)
1561 #if defined(JSON_HEDLEY_UNREACHABLE)
1562 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1564 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1567 #if defined(JSON_HEDLEY_UNREACHABLE)
1569 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1570 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1571 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1573 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1576 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1578 #if !defined(JSON_HEDLEY_UNREACHABLE)
1579 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1582 JSON_HEDLEY_DIAGNOSTIC_PUSH
1583 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1584 #pragma clang diagnostic ignored "-Wpedantic"
1586 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1587 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1589 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1590 #if defined(__clang__)
1591 #pragma clang diagnostic ignored "-Wvariadic-macros"
1592 #elif defined(JSON_HEDLEY_GCC_VERSION)
1593 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1596 #if defined(JSON_HEDLEY_NON_NULL)
1597 #undef JSON_HEDLEY_NON_NULL
1600 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1601 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1602 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1603 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1604 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1606 #define JSON_HEDLEY_NON_NULL(...)
1608 JSON_HEDLEY_DIAGNOSTIC_POP
1610 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1611 #undef JSON_HEDLEY_PRINTF_FORMAT
1613 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1614 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1615 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1616 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1618 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1619 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1622 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1623 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1624 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1625 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1626 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1627 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1628 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1630 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1632 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1633 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1634 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1635 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1636 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1642 #if defined(JSON_HEDLEY_CONSTEXPR)
1643 #undef JSON_HEDLEY_CONSTEXPR
1645 #if defined(__cplusplus)
1646 #if __cplusplus >= 201103L
1647 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1650 #if !defined(JSON_HEDLEY_CONSTEXPR)
1651 #define JSON_HEDLEY_CONSTEXPR
1654 #if defined(JSON_HEDLEY_PREDICT)
1655 #undef JSON_HEDLEY_PREDICT
1657 #if defined(JSON_HEDLEY_LIKELY)
1658 #undef JSON_HEDLEY_LIKELY
1660 #if defined(JSON_HEDLEY_UNLIKELY)
1661 #undef JSON_HEDLEY_UNLIKELY
1663 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1664 #undef JSON_HEDLEY_UNPREDICTABLE
1666 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1667 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1670 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1671 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1672 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1673 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1674 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1675 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1676 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1677 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1679 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1680 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1681 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1682 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1683 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1684 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1685 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1686 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1687 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1688 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1689 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1690 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1691 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1692 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1693 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1694 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1695 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1696 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1697 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1699 double hedley_probability_ = (probability); \
1700 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1702 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1704 double hedley_probability_ = (probability); \
1705 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1707 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1708 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1710 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1711 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1712 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1713 # define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1714 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1716 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1717 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1720 #if defined(JSON_HEDLEY_MALLOC)
1721 #undef JSON_HEDLEY_MALLOC
1724 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1725 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1726 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1727 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1728 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1729 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1730 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1731 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1732 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1733 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1734 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1735 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1737 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1739 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1740 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1741 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1742 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1743 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1744 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1746 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1747 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1748 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1750 #define JSON_HEDLEY_MALLOC
1753 #if defined(JSON_HEDLEY_PURE)
1754 #undef JSON_HEDLEY_PURE
1757 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1758 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1759 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1760 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1761 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1762 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1763 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1764 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1765 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1766 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1767 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1768 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1770 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1772 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1773 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1774 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1775 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1776 # define JSON_HEDLEY_PURE __attribute__((__pure__))
1777 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1778 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1779 #elif defined(__cplusplus) && \
1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1785 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1787 # define JSON_HEDLEY_PURE
1790 #if defined(JSON_HEDLEY_CONST)
1791 #undef JSON_HEDLEY_CONST
1794 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1795 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1796 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1797 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1798 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1799 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1800 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1801 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1802 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1803 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1804 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1805 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1807 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1809 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1810 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1811 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1812 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1813 #define JSON_HEDLEY_CONST __attribute__((__const__))
1815 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1816 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1818 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1821 #if defined(JSON_HEDLEY_RESTRICT)
1822 #undef JSON_HEDLEY_RESTRICT
1824 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1825 #define JSON_HEDLEY_RESTRICT restrict
1827 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1828 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1830 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1831 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1832 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1833 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1838 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1839 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1840 defined(__clang__) || \
1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1842 #define JSON_HEDLEY_RESTRICT __restrict
1843 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1844 #define JSON_HEDLEY_RESTRICT _Restrict
1846 #define JSON_HEDLEY_RESTRICT
1849 #if defined(JSON_HEDLEY_INLINE)
1850 #undef JSON_HEDLEY_INLINE
1853 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1854 (defined(__cplusplus) && (__cplusplus >= 199711L))
1855 #define JSON_HEDLEY_INLINE inline
1857 defined(JSON_HEDLEY_GCC_VERSION) || \
1858 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1859 #define JSON_HEDLEY_INLINE __inline__
1861 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1862 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1863 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1865 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1867 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1868 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1869 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1870 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1871 #define JSON_HEDLEY_INLINE __inline
1873 #define JSON_HEDLEY_INLINE
1876 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1877 #undef JSON_HEDLEY_ALWAYS_INLINE
1880 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1881 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1882 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1883 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1884 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1885 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1886 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1887 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1889 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1891 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1893 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1895 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1896 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1897 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1898 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1899 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1901 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1902 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1903 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1904 #elif defined(__cplusplus) && \
1906 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1907 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1908 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1910 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1911 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1913 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1914 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1915 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1917 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1920 #if defined(JSON_HEDLEY_NEVER_INLINE)
1921 #undef JSON_HEDLEY_NEVER_INLINE
1924 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1925 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1926 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1927 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1928 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1929 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1930 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1931 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1932 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1933 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1934 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1935 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1937 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1939 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1940 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1941 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1942 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1943 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1945 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1946 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1947 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1948 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1949 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1950 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1951 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1952 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1954 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1955 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1956 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1957 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1959 #define JSON_HEDLEY_NEVER_INLINE
1962 #if defined(JSON_HEDLEY_PRIVATE)
1963 #undef JSON_HEDLEY_PRIVATE
1965 #if defined(JSON_HEDLEY_PUBLIC)
1966 #undef JSON_HEDLEY_PUBLIC
1968 #if defined(JSON_HEDLEY_IMPORT)
1969 #undef JSON_HEDLEY_IMPORT
1971 #if defined(_WIN32) || defined(__CYGWIN__)
1972 # define JSON_HEDLEY_PRIVATE
1973 # define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1974 # define JSON_HEDLEY_IMPORT __declspec(dllimport)
1977 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1978 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1979 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1980 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1981 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1982 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1984 defined(__TI_EABI__) && \
1986 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1990 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1991 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1992 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1994 # define JSON_HEDLEY_PRIVATE
1995 # define JSON_HEDLEY_PUBLIC
1997 # define JSON_HEDLEY_IMPORT extern
2000 #if defined(JSON_HEDLEY_NO_THROW)
2001 #undef JSON_HEDLEY_NO_THROW
2004 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2005 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2006 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2007 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2008 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2010 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2011 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2012 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2013 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2015 #define JSON_HEDLEY_NO_THROW
2018 #if defined(JSON_HEDLEY_FALL_THROUGH)
2019 #undef JSON_HEDLEY_FALL_THROUGH
2022 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2023 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2024 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2025 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2026 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2027 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2028 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2029 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2030 #elif defined(__fallthrough) /* SAL */
2031 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2033 #define JSON_HEDLEY_FALL_THROUGH
2036 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2037 #undef JSON_HEDLEY_RETURNS_NON_NULL
2040 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2041 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2042 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2043 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2044 #elif defined(_Ret_notnull_) /* SAL */
2045 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2047 #define JSON_HEDLEY_RETURNS_NON_NULL
2050 #if defined(JSON_HEDLEY_ARRAY_PARAM)
2051 #undef JSON_HEDLEY_ARRAY_PARAM
2054 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2055 !defined(__STDC_NO_VLA__) && \
2056 !defined(__cplusplus) && \
2057 !defined(JSON_HEDLEY_PGI_VERSION) && \
2058 !defined(JSON_HEDLEY_TINYC_VERSION)
2059 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2061 #define JSON_HEDLEY_ARRAY_PARAM(name)
2064 #if defined(JSON_HEDLEY_IS_CONSTANT)
2065 #undef JSON_HEDLEY_IS_CONSTANT
2067 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2068 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2070 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
2071 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2072 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2073 #undef JSON_HEDLEY_IS_CONSTEXPR_
2076 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2077 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2078 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2080 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2081 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2083 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2084 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2085 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2086 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2088 #if !defined(__cplusplus)
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2094 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2095 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2096 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2097 #if defined(__INTPTR_TYPE__)
2098 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2101 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2105 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2106 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2107 !defined(JSON_HEDLEY_PGI_VERSION) && \
2108 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2109 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2110 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2111 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2112 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2113 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2114 #if defined(__INTPTR_TYPE__)
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2118 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2121 defined(JSON_HEDLEY_GCC_VERSION) || \
2122 defined(JSON_HEDLEY_INTEL_VERSION) || \
2123 defined(JSON_HEDLEY_TINYC_VERSION) || \
2124 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2125 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2126 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2127 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2128 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2129 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2131 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2135 ((void*) ((expr) * 0L) ) : \
2136 ((struct { char v[sizeof(void) * 2]; } *) 1) \
2142 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2143 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2144 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2146 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2148 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2149 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2151 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2154 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2155 #undef JSON_HEDLEY_BEGIN_C_DECLS
2157 #if defined(JSON_HEDLEY_END_C_DECLS)
2158 #undef JSON_HEDLEY_END_C_DECLS
2160 #if defined(JSON_HEDLEY_C_DECL)
2161 #undef JSON_HEDLEY_C_DECL
2163 #if defined(__cplusplus)
2164 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2165 #define JSON_HEDLEY_END_C_DECLS }
2166 #define JSON_HEDLEY_C_DECL extern "C"
2168 #define JSON_HEDLEY_BEGIN_C_DECLS
2169 #define JSON_HEDLEY_END_C_DECLS
2170 #define JSON_HEDLEY_C_DECL
2173 #if defined(JSON_HEDLEY_STATIC_ASSERT)
2174 #undef JSON_HEDLEY_STATIC_ASSERT
2177 !defined(__cplusplus) && ( \
2178 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2179 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2180 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2181 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2182 defined(_Static_assert) \
2184 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2186 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2187 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2188 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2189 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2191 # define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2194 #if defined(JSON_HEDLEY_NULL)
2195 #undef JSON_HEDLEY_NULL
2197 #if defined(__cplusplus)
2198 #if __cplusplus >= 201103L
2199 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2201 #define JSON_HEDLEY_NULL NULL
2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2206 #define JSON_HEDLEY_NULL NULL
2208 #define JSON_HEDLEY_NULL ((void*) 0)
2211 #if defined(JSON_HEDLEY_MESSAGE)
2212 #undef JSON_HEDLEY_MESSAGE
2214 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2215 # define JSON_HEDLEY_MESSAGE(msg) \
2216 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2217 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2218 JSON_HEDLEY_PRAGMA(message msg) \
2219 JSON_HEDLEY_DIAGNOSTIC_POP
2221 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2222 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2223 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2224 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2225 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2226 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2227 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2228 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2229 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2231 # define JSON_HEDLEY_MESSAGE(msg)
2234 #if defined(JSON_HEDLEY_WARNING)
2235 #undef JSON_HEDLEY_WARNING
2237 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2238 # define JSON_HEDLEY_WARNING(msg) \
2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2241 JSON_HEDLEY_PRAGMA(clang warning msg) \
2242 JSON_HEDLEY_DIAGNOSTIC_POP
2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2245 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2247 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2249 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2250 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2251 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2253 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2256 #if defined(JSON_HEDLEY_REQUIRE)
2257 #undef JSON_HEDLEY_REQUIRE
2259 #if defined(JSON_HEDLEY_REQUIRE_MSG)
2260 #undef JSON_HEDLEY_REQUIRE_MSG
2262 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2263 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2264 # define JSON_HEDLEY_REQUIRE(expr) \
2265 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2266 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2267 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2268 JSON_HEDLEY_DIAGNOSTIC_POP
2269 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2270 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2271 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2272 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2273 JSON_HEDLEY_DIAGNOSTIC_POP
2275 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2276 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2279 # define JSON_HEDLEY_REQUIRE(expr)
2280 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2283 #if defined(JSON_HEDLEY_FLAGS)
2284 #undef JSON_HEDLEY_FLAGS
2286 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2287 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2289 #define JSON_HEDLEY_FLAGS
2292 #if defined(JSON_HEDLEY_FLAGS_CAST)
2293 #undef JSON_HEDLEY_FLAGS_CAST
2295 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2296 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2297 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2298 _Pragma("warning(disable:188)") \
2300 JSON_HEDLEY_DIAGNOSTIC_POP \
2303 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2306 #if defined(JSON_HEDLEY_EMPTY_BASES)
2307 #undef JSON_HEDLEY_EMPTY_BASES
2310 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2311 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2312 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2314 #define JSON_HEDLEY_EMPTY_BASES
2317 /* Remaining macros are deprecated. */
2319 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2320 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2322 #if defined(__clang__)
2323 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2325 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2328 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2329 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2331 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2333 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2334 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2336 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2338 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2339 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2341 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2343 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2344 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2346 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2348 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2349 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2351 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2353 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2354 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2356 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2358 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2359 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2361 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2363 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2366 // This file contains all internal macro definitions (except those affecting ABI)
2367 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2369 // #include <nlohmann/detail/abi_macros.hpp>
2372 // exclude unsupported compilers
2373 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2374 #if defined(__clang__)
2375 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2376 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2378 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2379 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2380 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2385 // C++ language standard detection
2386 // if the user manually specified the used c++ version this is skipped
2387 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2388 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2389 #define JSON_HAS_CPP_20
2390 #define JSON_HAS_CPP_17
2391 #define JSON_HAS_CPP_14
2392 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2393 #define JSON_HAS_CPP_17
2394 #define JSON_HAS_CPP_14
2395 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2396 #define JSON_HAS_CPP_14
2398 // the cpp 11 flag is always specified because it is the minimal required version
2399 #define JSON_HAS_CPP_11
2402 #ifdef __has_include
2403 #if __has_include(<version>)
2408 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2409 #ifdef JSON_HAS_CPP_17
2410 #if defined(__cpp_lib_filesystem)
2411 #define JSON_HAS_FILESYSTEM 1
2412 #elif defined(__cpp_lib_experimental_filesystem)
2413 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2414 #elif !defined(__has_include)
2415 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2416 #elif __has_include(<filesystem>)
2417 #define JSON_HAS_FILESYSTEM 1
2418 #elif __has_include(<experimental/filesystem>)
2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2422 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2423 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2424 #undef JSON_HAS_FILESYSTEM
2425 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2428 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2429 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2430 #undef JSON_HAS_FILESYSTEM
2431 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2434 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2435 #if defined(__clang_major__) && __clang_major__ < 7
2436 #undef JSON_HAS_FILESYSTEM
2437 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2440 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2441 #if defined(_MSC_VER) && _MSC_VER < 1914
2442 #undef JSON_HAS_FILESYSTEM
2443 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2446 // no filesystem support before iOS 13
2447 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2448 #undef JSON_HAS_FILESYSTEM
2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2452 // no filesystem support before macOS Catalina
2453 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2454 #undef JSON_HAS_FILESYSTEM
2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2464 #ifndef JSON_HAS_FILESYSTEM
2465 #define JSON_HAS_FILESYSTEM 0
2468 #ifndef JSON_HAS_THREE_WAY_COMPARISON
2469 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2470 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2471 #define JSON_HAS_THREE_WAY_COMPARISON 1
2473 #define JSON_HAS_THREE_WAY_COMPARISON 0
2477 #ifndef JSON_HAS_RANGES
2478 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2479 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2480 #define JSON_HAS_RANGES 0
2481 #elif defined(__cpp_lib_ranges)
2482 #define JSON_HAS_RANGES 1
2484 #define JSON_HAS_RANGES 0
2488 #ifdef JSON_HAS_CPP_17
2489 #define JSON_INLINE_VARIABLE inline
2491 #define JSON_INLINE_VARIABLE
2494 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2495 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2497 #define JSON_NO_UNIQUE_ADDRESS
2500 // disable documentation warnings on clang
2501 #if defined(__clang__)
2502 #pragma clang diagnostic push
2503 #pragma clang diagnostic ignored "-Wdocumentation"
2504 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2507 // allow disabling exceptions
2508 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2509 #define JSON_THROW(exception) throw exception
2510 #define JSON_TRY try
2511 #define JSON_CATCH(exception) catch(exception)
2512 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2515 #define JSON_THROW(exception) std::abort()
2516 #define JSON_TRY if(true)
2517 #define JSON_CATCH(exception) if(false)
2518 #define JSON_INTERNAL_CATCH(exception) if(false)
2521 // override exception macros
2522 #if defined(JSON_THROW_USER)
2524 #define JSON_THROW JSON_THROW_USER
2526 #if defined(JSON_TRY_USER)
2528 #define JSON_TRY JSON_TRY_USER
2530 #if defined(JSON_CATCH_USER)
2532 #define JSON_CATCH JSON_CATCH_USER
2533 #undef JSON_INTERNAL_CATCH
2534 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2536 #if defined(JSON_INTERNAL_CATCH_USER)
2537 #undef JSON_INTERNAL_CATCH
2538 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2541 // allow overriding assert
2542 #if !defined(JSON_ASSERT)
2543 #include <cassert> // assert
2544 #define JSON_ASSERT(x) assert(x)
2547 // allow to access some private functions (needed by the test suite)
2548 #if defined(JSON_TESTS_PRIVATE)
2549 #define JSON_PRIVATE_UNLESS_TESTED public
2551 #define JSON_PRIVATE_UNLESS_TESTED private
2555 @brief macro to briefly define a mapping between an enum and JSON
2556 @def NLOHMANN_JSON_SERIALIZE_ENUM
2557 @since version 3.4.0
2559 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2560 template<typename BasicJsonType> \
2561 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2563 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2564 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2565 auto it = std::find_if(std::begin(m), std::end(m), \
2566 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2568 return ej_pair.first == e; \
2570 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2572 template<typename BasicJsonType> \
2573 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2575 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2576 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2577 auto it = std::find_if(std::begin(m), std::end(m), \
2578 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2580 return ej_pair.second == j; \
2582 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2585 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2586 // may be removed in the future once the class is split.
2588 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2589 template<template<typename, typename, typename...> class ObjectType, \
2590 template<typename, typename...> class ArrayType, \
2591 class StringType, class BooleanType, class NumberIntegerType, \
2592 class NumberUnsignedType, class NumberFloatType, \
2593 template<typename> class AllocatorType, \
2594 template<typename, typename = void> class JSONSerializer, \
2596 class CustomBaseClass>
2598 #define NLOHMANN_BASIC_JSON_TPL \
2599 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2600 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2601 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2603 // Macros to simplify conversion from/to types
2605 #define NLOHMANN_JSON_EXPAND( x ) x
2606 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2607 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2608 NLOHMANN_JSON_PASTE64, \
2609 NLOHMANN_JSON_PASTE63, \
2610 NLOHMANN_JSON_PASTE62, \
2611 NLOHMANN_JSON_PASTE61, \
2612 NLOHMANN_JSON_PASTE60, \
2613 NLOHMANN_JSON_PASTE59, \
2614 NLOHMANN_JSON_PASTE58, \
2615 NLOHMANN_JSON_PASTE57, \
2616 NLOHMANN_JSON_PASTE56, \
2617 NLOHMANN_JSON_PASTE55, \
2618 NLOHMANN_JSON_PASTE54, \
2619 NLOHMANN_JSON_PASTE53, \
2620 NLOHMANN_JSON_PASTE52, \
2621 NLOHMANN_JSON_PASTE51, \
2622 NLOHMANN_JSON_PASTE50, \
2623 NLOHMANN_JSON_PASTE49, \
2624 NLOHMANN_JSON_PASTE48, \
2625 NLOHMANN_JSON_PASTE47, \
2626 NLOHMANN_JSON_PASTE46, \
2627 NLOHMANN_JSON_PASTE45, \
2628 NLOHMANN_JSON_PASTE44, \
2629 NLOHMANN_JSON_PASTE43, \
2630 NLOHMANN_JSON_PASTE42, \
2631 NLOHMANN_JSON_PASTE41, \
2632 NLOHMANN_JSON_PASTE40, \
2633 NLOHMANN_JSON_PASTE39, \
2634 NLOHMANN_JSON_PASTE38, \
2635 NLOHMANN_JSON_PASTE37, \
2636 NLOHMANN_JSON_PASTE36, \
2637 NLOHMANN_JSON_PASTE35, \
2638 NLOHMANN_JSON_PASTE34, \
2639 NLOHMANN_JSON_PASTE33, \
2640 NLOHMANN_JSON_PASTE32, \
2641 NLOHMANN_JSON_PASTE31, \
2642 NLOHMANN_JSON_PASTE30, \
2643 NLOHMANN_JSON_PASTE29, \
2644 NLOHMANN_JSON_PASTE28, \
2645 NLOHMANN_JSON_PASTE27, \
2646 NLOHMANN_JSON_PASTE26, \
2647 NLOHMANN_JSON_PASTE25, \
2648 NLOHMANN_JSON_PASTE24, \
2649 NLOHMANN_JSON_PASTE23, \
2650 NLOHMANN_JSON_PASTE22, \
2651 NLOHMANN_JSON_PASTE21, \
2652 NLOHMANN_JSON_PASTE20, \
2653 NLOHMANN_JSON_PASTE19, \
2654 NLOHMANN_JSON_PASTE18, \
2655 NLOHMANN_JSON_PASTE17, \
2656 NLOHMANN_JSON_PASTE16, \
2657 NLOHMANN_JSON_PASTE15, \
2658 NLOHMANN_JSON_PASTE14, \
2659 NLOHMANN_JSON_PASTE13, \
2660 NLOHMANN_JSON_PASTE12, \
2661 NLOHMANN_JSON_PASTE11, \
2662 NLOHMANN_JSON_PASTE10, \
2663 NLOHMANN_JSON_PASTE9, \
2664 NLOHMANN_JSON_PASTE8, \
2665 NLOHMANN_JSON_PASTE7, \
2666 NLOHMANN_JSON_PASTE6, \
2667 NLOHMANN_JSON_PASTE5, \
2668 NLOHMANN_JSON_PASTE4, \
2669 NLOHMANN_JSON_PASTE3, \
2670 NLOHMANN_JSON_PASTE2, \
2671 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2672 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2673 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2674 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2675 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2676 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2677 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2678 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2679 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2680 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2681 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2682 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2683 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2684 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2685 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2686 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2687 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2688 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2689 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2690 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2691 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2692 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2693 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2694 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2695 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2696 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2697 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2698 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2699 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2700 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2701 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2702 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2703 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2704 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2705 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2706 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2707 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2708 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2709 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2710 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2711 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2712 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2713 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2714 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2715 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2716 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2717 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2718 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2719 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2720 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2721 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2722 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2723 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2724 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2725 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2726 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2727 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2728 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2729 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2730 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2731 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2732 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2733 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2734 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2736 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2737 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2738 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2742 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2743 @since version 3.9.0
2745 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2746 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2747 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2749 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2750 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2751 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2755 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2756 @since version 3.9.0
2758 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2759 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2760 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2762 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2763 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2764 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2767 // inspired from https://stackoverflow.com/a/26745591
2768 // allows to call any std function as if (e.g. with begin):
2769 // using std::begin; begin(x);
2771 // it allows using the detected idiom to retrieve the return type
2772 // of such an expression
2773 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2774 namespace detail { \
2775 using std::std_name; \
2777 template<typename... T> \
2778 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2781 namespace detail2 { \
2782 struct std_name##_tag \
2786 template<typename... T> \
2787 std_name##_tag std_name(T&&...); \
2789 template<typename... T> \
2790 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2792 template<typename... T> \
2793 struct would_call_std_##std_name \
2795 static constexpr auto const value = ::nlohmann::detail:: \
2796 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2798 } /* namespace detail2 */ \
2800 template<typename... T> \
2801 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2805 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2806 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2809 #if JSON_USE_IMPLICIT_CONVERSIONS
2810 #define JSON_EXPLICIT
2812 #define JSON_EXPLICIT explicit
2815 #ifndef JSON_DISABLE_ENUM_SERIALIZATION
2816 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2819 #ifndef JSON_USE_GLOBAL_UDLS
2820 #define JSON_USE_GLOBAL_UDLS 1
2823 #if JSON_HAS_THREE_WAY_COMPARISON
2824 #include <compare> // partial_ordering
2827 NLOHMANN_JSON_NAMESPACE_BEGIN
2831 ///////////////////////////
2832 // JSON type enumeration //
2833 ///////////////////////////
2836 @brief the JSON type enumeration
2838 This enumeration collects the different JSON types. It is internally used to
2839 distinguish the stored values, and the functions @ref basic_json::is_null(),
2840 @ref basic_json::is_object(), @ref basic_json::is_array(),
2841 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
2842 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2843 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2844 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2845 @ref basic_json::is_structured() rely on it.
2847 @note There are three enumeration entries (number_integer, number_unsigned, and
2848 number_float), because the library distinguishes these three types for numbers:
2849 @ref basic_json::number_unsigned_t is used for unsigned integers,
2850 @ref basic_json::number_integer_t is used for signed integers, and
2851 @ref basic_json::number_float_t is used for floating-point numbers or to
2852 approximate integers which do not fit in the limits of their respective type.
2854 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2855 value with the default value for a given type
2857 @since version 1.0.0
2859 enum class value_t : std::uint8_t
2861 null, ///< null value
2862 object, ///< object (unordered set of name/value pairs)
2863 array, ///< array (ordered collection of values)
2864 string, ///< string value
2865 boolean, ///< boolean value
2866 number_integer, ///< number value (signed integer)
2867 number_unsigned, ///< number value (unsigned integer)
2868 number_float, ///< number value (floating-point)
2869 binary, ///< binary array (ordered collection of bytes)
2870 discarded ///< discarded by the parser callback function
2874 @brief comparison operator for JSON types
2876 Returns an ordering that is similar to Python:
2877 - order: null < boolean < number < object < array < string < binary
2878 - furthermore, each type is not smaller than itself
2879 - discarded values are not comparable
2880 - binary is represented as a b"" string in python and directly comparable to a
2881 string; however, making a binary array directly comparable with a string would
2882 be surprising behavior in a JSON file.
2884 @since version 1.0.0
2886 #if JSON_HAS_THREE_WAY_COMPARISON
2887 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2889 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2892 static constexpr std::array<std::uint8_t, 9> order = {{
2893 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2894 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2899 const auto l_index = static_cast<std::size_t>(lhs);
2900 const auto r_index = static_cast<std::size_t>(rhs);
2901 #if JSON_HAS_THREE_WAY_COMPARISON
2902 if (l_index < order.size() && r_index < order.size())
2904 return order[l_index] <=> order[r_index]; // *NOPAD*
2906 return std::partial_ordering::unordered;
2908 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2912 // GCC selects the built-in operator< over an operator rewritten from
2913 // a user-defined spaceship operator
2914 // Clang, MSVC, and ICC select the rewritten candidate
2915 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2916 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2917 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2919 return std::is_lt(lhs <=> rhs); // *NOPAD*
2923 } // namespace detail
2924 NLOHMANN_JSON_NAMESPACE_END
2926 // #include <nlohmann/detail/string_escape.hpp>
2927 // __ _____ _____ _____
2928 // __| | __| | | | JSON for Modern C++
2929 // | | |__ | | | | | | version 3.11.2
2930 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
2932 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
2933 // SPDX-License-Identifier: MIT
2937 // #include <nlohmann/detail/abi_macros.hpp>
2940 NLOHMANN_JSON_NAMESPACE_BEGIN
2945 @brief replace all occurrences of a substring by another string
2947 @param[in,out] s the string to manipulate; changed so that all
2948 occurrences of @a f are replaced with @a t
2949 @param[in] f the substring to replace with @a t
2950 @param[in] t the string to replace @a f
2952 @pre The search string @a f must not be empty. **This precondition is
2953 enforced with an assertion.**
2955 @since version 2.0.0
2957 template<typename StringType>
2958 inline void replace_substring(StringType& s, const StringType& f,
2959 const StringType& t)
2961 JSON_ASSERT(!f.empty());
2962 for (auto pos = s.find(f); // find first occurrence of f
2963 pos != StringType::npos; // make sure f was found
2964 s.replace(pos, f.size(), t), // replace with t, and
2965 pos = s.find(f, pos + t.size())) // find next occurrence of f
2970 * @brief string escaping as described in RFC 6901 (Sect. 4)
2971 * @param[in] s string to escape
2972 * @return escaped string
2974 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
2976 template<typename StringType>
2977 inline StringType escape(StringType s)
2979 replace_substring(s, StringType{"~"}, StringType{"~0"});
2980 replace_substring(s, StringType{"/"}, StringType{"~1"});
2985 * @brief string unescaping as described in RFC 6901 (Sect. 4)
2986 * @param[in] s string to unescape
2987 * @return unescaped string
2989 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
2991 template<typename StringType>
2992 static void unescape(StringType& s)
2994 replace_substring(s, StringType{"~1"}, StringType{"/"});
2995 replace_substring(s, StringType{"~0"}, StringType{"~"});
2998 } // namespace detail
2999 NLOHMANN_JSON_NAMESPACE_END
3001 // #include <nlohmann/detail/input/position_t.hpp>
3002 // __ _____ _____ _____
3003 // __| | __| | | | JSON for Modern C++
3004 // | | |__ | | | | | | version 3.11.2
3005 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3007 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3008 // SPDX-License-Identifier: MIT
3012 #include <cstddef> // size_t
3014 // #include <nlohmann/detail/abi_macros.hpp>
3017 NLOHMANN_JSON_NAMESPACE_BEGIN
3021 /// struct to capture the start position of the current token
3024 /// the total number of characters read
3025 std::size_t chars_read_total = 0;
3026 /// the number of characters read in the current line
3027 std::size_t chars_read_current_line = 0;
3028 /// the number of lines read
3029 std::size_t lines_read = 0;
3031 /// conversion to size_t to preserve SAX interface
3032 constexpr operator size_t() const
3034 return chars_read_total;
3038 } // namespace detail
3039 NLOHMANN_JSON_NAMESPACE_END
3041 // #include <nlohmann/detail/macro_scope.hpp>
3043 // #include <nlohmann/detail/meta/cpp_future.hpp>
3044 // __ _____ _____ _____
3045 // __| | __| | | | JSON for Modern C++
3046 // | | |__ | | | | | | version 3.11.2
3047 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3049 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3050 // SPDX-FileCopyrightText: 2018 The Abseil Authors
3051 // SPDX-License-Identifier: MIT
3055 #include <array> // array
3056 #include <cstddef> // size_t
3057 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3058 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
3060 // #include <nlohmann/detail/macro_scope.hpp>
3063 NLOHMANN_JSON_NAMESPACE_BEGIN
3067 template<typename T>
3068 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3070 #ifdef JSON_HAS_CPP_14
3072 // the following utilities are natively available in C++14
3073 using std::enable_if_t;
3074 using std::index_sequence;
3075 using std::make_index_sequence;
3076 using std::index_sequence_for;
3080 // alias templates to reduce boilerplate
3081 template<bool B, typename T = void>
3082 using enable_if_t = typename std::enable_if<B, T>::type;
3084 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3085 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3087 //// START OF CODE FROM GOOGLE ABSEIL
3091 // Class template representing a compile-time integer sequence. An instantiation
3092 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3093 // type through its template arguments (which is a common need when
3094 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3095 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3099 // template< class T, T... Ints >
3100 // void user_function(integer_sequence<T, Ints...>);
3104 // // user_function's `T` will be deduced to `int` and `Ints...`
3105 // // will be deduced to `0, 1, 2, 3, 4`.
3106 // user_function(make_integer_sequence<int, 5>());
3108 template <typename T, T... Ints>
3109 struct integer_sequence
3111 using value_type = T;
3112 static constexpr std::size_t size() noexcept
3114 return sizeof...(Ints);
3120 // A helper template for an `integer_sequence` of `size_t`,
3121 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3122 // `std::index_sequence`.
3123 template <size_t... Ints>
3124 using index_sequence = integer_sequence<size_t, Ints...>;
3126 namespace utility_internal
3129 template <typename Seq, size_t SeqSize, size_t Rem>
3132 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3133 template <typename T, T... Ints, size_t SeqSize>
3134 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3136 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3139 template <typename T, T... Ints, size_t SeqSize>
3140 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3142 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3145 // Recursion helper for 'make_integer_sequence<T, N>'.
3146 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3147 template <typename T, size_t N>
3151 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3154 template <typename T>
3157 using type = integer_sequence<T>;
3160 } // namespace utility_internal
3162 // Compile-time sequences of integers
3164 // make_integer_sequence
3166 // This template alias is equivalent to
3167 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3168 // replacement for C++14's `std::make_integer_sequence`.
3169 template <typename T, T N>
3170 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3172 // make_index_sequence
3174 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3175 // and is designed to be a drop-in replacement for C++14's
3176 // `std::make_index_sequence`.
3178 using make_index_sequence = make_integer_sequence<size_t, N>;
3180 // index_sequence_for
3182 // Converts a typename pack into an index sequence of the same length, and
3183 // is designed to be a drop-in replacement for C++14's
3184 // `std::index_sequence_for()`
3185 template <typename... Ts>
3186 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3188 //// END OF CODE FROM GOOGLE ABSEIL
3192 // dispatch utility (taken from ranges-v3)
3193 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3194 template<> struct priority_tag<0> {};
3196 // taken from ranges-v3
3197 template<typename T>
3200 static JSON_INLINE_VARIABLE constexpr T value{};
3203 #ifndef JSON_HAS_CPP_17
3204 template<typename T>
3205 constexpr T static_const<T>::value;
3208 template<typename T, typename... Args>
3209 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3211 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3214 } // namespace detail
3215 NLOHMANN_JSON_NAMESPACE_END
3217 // #include <nlohmann/detail/meta/type_traits.hpp>
3218 // __ _____ _____ _____
3219 // __| | __| | | | JSON for Modern C++
3220 // | | |__ | | | | | | version 3.11.2
3221 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3223 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3224 // SPDX-License-Identifier: MIT
3228 #include <limits> // numeric_limits
3229 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3230 #include <utility> // declval
3231 #include <tuple> // tuple
3233 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3234 // __ _____ _____ _____
3235 // __| | __| | | | JSON for Modern C++
3236 // | | |__ | | | | | | version 3.11.2
3237 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3240 // SPDX-License-Identifier: MIT
3244 #include <iterator> // random_access_iterator_tag
3246 // #include <nlohmann/detail/abi_macros.hpp>
3248 // #include <nlohmann/detail/meta/void_t.hpp>
3250 // #include <nlohmann/detail/meta/cpp_future.hpp>
3253 NLOHMANN_JSON_NAMESPACE_BEGIN
3257 template<typename It, typename = void>
3258 struct iterator_types {};
3260 template<typename It>
3261 struct iterator_types <
3263 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3264 typename It::reference, typename It::iterator_category >>
3266 using difference_type = typename It::difference_type;
3267 using value_type = typename It::value_type;
3268 using pointer = typename It::pointer;
3269 using reference = typename It::reference;
3270 using iterator_category = typename It::iterator_category;
3273 // This is required as some compilers implement std::iterator_traits in a way that
3274 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3275 template<typename T, typename = void>
3276 struct iterator_traits
3280 template<typename T>
3281 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3286 template<typename T>
3287 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3289 using iterator_category = std::random_access_iterator_tag;
3290 using value_type = T;
3291 using difference_type = ptrdiff_t;
3293 using reference = T&;
3296 } // namespace detail
3297 NLOHMANN_JSON_NAMESPACE_END
3299 // #include <nlohmann/detail/macro_scope.hpp>
3301 // #include <nlohmann/detail/meta/call_std/begin.hpp>
3302 // __ _____ _____ _____
3303 // __| | __| | | | JSON for Modern C++
3304 // | | |__ | | | | | | version 3.11.2
3305 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3307 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3308 // SPDX-License-Identifier: MIT
3312 // #include <nlohmann/detail/macro_scope.hpp>
3315 NLOHMANN_JSON_NAMESPACE_BEGIN
3317 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3319 NLOHMANN_JSON_NAMESPACE_END
3321 // #include <nlohmann/detail/meta/call_std/end.hpp>
3322 // __ _____ _____ _____
3323 // __| | __| | | | JSON for Modern C++
3324 // | | |__ | | | | | | version 3.11.2
3325 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3327 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3328 // SPDX-License-Identifier: MIT
3332 // #include <nlohmann/detail/macro_scope.hpp>
3335 NLOHMANN_JSON_NAMESPACE_BEGIN
3337 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3339 NLOHMANN_JSON_NAMESPACE_END
3341 // #include <nlohmann/detail/meta/cpp_future.hpp>
3343 // #include <nlohmann/detail/meta/detected.hpp>
3345 // #include <nlohmann/json_fwd.hpp>
3346 // __ _____ _____ _____
3347 // __| | __| | | | JSON for Modern C++
3348 // | | |__ | | | | | | version 3.11.2
3349 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
3351 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
3352 // SPDX-License-Identifier: MIT
3354 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3355 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3357 #include <cstdint> // int64_t, uint64_t
3358 #include <map> // map
3359 #include <memory> // allocator
3360 #include <string> // string
3361 #include <vector> // vector
3363 // #include <nlohmann/detail/abi_macros.hpp>
3367 @brief namespace for Niels Lohmann
3368 @see https://github.com/nlohmann
3369 @since version 1.0.0
3371 NLOHMANN_JSON_NAMESPACE_BEGIN
3374 @brief default JSONSerializer template argument
3376 This serializer ignores the template arguments and uses ADL
3377 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3380 template<typename T = void, typename SFINAE = void>
3381 struct adl_serializer;
3383 /// a class to store JSON values
3384 /// @sa https://json.nlohmann.me/api/basic_json/
3385 template<template<typename U, typename V, typename... Args> class ObjectType =
3387 template<typename U, typename... Args> class ArrayType = std::vector,
3388 class StringType = std::string, class BooleanType = bool,
3389 class NumberIntegerType = std::int64_t,
3390 class NumberUnsignedType = std::uint64_t,
3391 class NumberFloatType = double,
3392 template<typename U> class AllocatorType = std::allocator,
3393 template<typename T, typename SFINAE = void> class JSONSerializer =
3395 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3396 class CustomBaseClass = void>
3399 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3400 /// @sa https://json.nlohmann.me/api/json_pointer/
3401 template<typename RefStringType>
3405 @brief default specialization
3406 @sa https://json.nlohmann.me/api/json/
3408 using json = basic_json<>;
3410 /// @brief a minimal map-like container that preserves insertion order
3411 /// @sa https://json.nlohmann.me/api/ordered_map/
3412 template<class Key, class T, class IgnoredLess, class Allocator>
3415 /// @brief specialization that maintains the insertion order of object keys
3416 /// @sa https://json.nlohmann.me/api/ordered_json/
3417 using ordered_json = basic_json<nlohmann::ordered_map>;
3419 NLOHMANN_JSON_NAMESPACE_END
3421 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3424 NLOHMANN_JSON_NAMESPACE_BEGIN
3426 @brief detail namespace with internal helper functions
3428 This namespace collects functions that should not be exposed,
3429 implementations of some @ref basic_json methods, and meta-programming helpers.
3431 @since version 2.1.0
3440 // Note to maintainers:
3442 // Every trait in this file expects a non CV-qualified type.
3443 // The only exceptions are in the 'aliases for detected' section
3444 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3446 // In this case, T has to be properly CV-qualified to constraint the function arguments
3447 // (e.g. to_json(BasicJsonType&, const T&))
3449 template<typename> struct is_basic_json : std::false_type {};
3451 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3452 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3454 // used by exceptions create() member functions
3455 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3456 // false_type otherwise
3457 template<typename BasicJsonContext>
3458 struct is_basic_json_context :
3459 std::integral_constant < bool,
3460 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3461 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3464 //////////////////////
3465 // json_ref helpers //
3466 //////////////////////
3472 struct is_json_ref : std::false_type {};
3474 template<typename T>
3475 struct is_json_ref<json_ref<T>> : std::true_type {};
3477 //////////////////////////
3478 // aliases for detected //
3479 //////////////////////////
3481 template<typename T>
3482 using mapped_type_t = typename T::mapped_type;
3484 template<typename T>
3485 using key_type_t = typename T::key_type;
3487 template<typename T>
3488 using value_type_t = typename T::value_type;
3490 template<typename T>
3491 using difference_type_t = typename T::difference_type;
3493 template<typename T>
3494 using pointer_t = typename T::pointer;
3496 template<typename T>
3497 using reference_t = typename T::reference;
3499 template<typename T>
3500 using iterator_category_t = typename T::iterator_category;
3502 template<typename T, typename... Args>
3503 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3505 template<typename T, typename... Args>
3506 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3508 template<typename T, typename U>
3509 using get_template_function = decltype(std::declval<T>().template get<U>());
3511 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3512 template<typename BasicJsonType, typename T, typename = void>
3513 struct has_from_json : std::false_type {};
3515 // trait checking if j.get<T> is valid
3516 // use this trait instead of std::is_constructible or std::is_convertible,
3517 // both rely on, or make use of implicit conversions, and thus fail when T
3518 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3519 template <typename BasicJsonType, typename T>
3522 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3525 template<typename BasicJsonType, typename T>
3526 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3528 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3530 static constexpr bool value =
3531 is_detected_exact<void, from_json_function, serializer,
3532 const BasicJsonType&, T&>::value;
3535 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3536 // this overload is used for non-default-constructible user-defined-types
3537 template<typename BasicJsonType, typename T, typename = void>
3538 struct has_non_default_from_json : std::false_type {};
3540 template<typename BasicJsonType, typename T>
3541 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3543 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3545 static constexpr bool value =
3546 is_detected_exact<T, from_json_function, serializer,
3547 const BasicJsonType&>::value;
3550 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3551 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3552 template<typename BasicJsonType, typename T, typename = void>
3553 struct has_to_json : std::false_type {};
3555 template<typename BasicJsonType, typename T>
3556 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3558 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3560 static constexpr bool value =
3561 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3565 template<typename T>
3566 using detect_key_compare = typename T::key_compare;
3568 template<typename T>
3569 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3571 // obtains the actual object key comparator
3572 template<typename BasicJsonType>
3573 struct actual_object_comparator
3575 using object_t = typename BasicJsonType::object_t;
3576 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3577 using type = typename std::conditional < has_key_compare<object_t>::value,
3578 typename object_t::key_compare, object_comparator_t>::type;
3581 template<typename BasicJsonType>
3582 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3588 // https://en.cppreference.com/w/cpp/types/conjunction
3589 template<class...> struct conjunction : std::true_type { };
3590 template<class B> struct conjunction<B> : B { };
3591 template<class B, class... Bn>
3592 struct conjunction<B, Bn...>
3593 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3595 // https://en.cppreference.com/w/cpp/types/negation
3596 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3598 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3599 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3600 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3601 template <typename T>
3602 struct is_default_constructible : std::is_default_constructible<T> {};
3604 template <typename T1, typename T2>
3605 struct is_default_constructible<std::pair<T1, T2>>
3606 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3608 template <typename T1, typename T2>
3609 struct is_default_constructible<const std::pair<T1, T2>>
3610 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3612 template <typename... Ts>
3613 struct is_default_constructible<std::tuple<Ts...>>
3614 : conjunction<is_default_constructible<Ts>...> {};
3616 template <typename... Ts>
3617 struct is_default_constructible<const std::tuple<Ts...>>
3618 : conjunction<is_default_constructible<Ts>...> {};
3621 template <typename T, typename... Args>
3622 struct is_constructible : std::is_constructible<T, Args...> {};
3624 template <typename T1, typename T2>
3625 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3627 template <typename T1, typename T2>
3628 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3630 template <typename... Ts>
3631 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3633 template <typename... Ts>
3634 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3637 template<typename T, typename = void>
3638 struct is_iterator_traits : std::false_type {};
3640 template<typename T>
3641 struct is_iterator_traits<iterator_traits<T>>
3644 using traits = iterator_traits<T>;
3647 static constexpr auto value =
3648 is_detected<value_type_t, traits>::value &&
3649 is_detected<difference_type_t, traits>::value &&
3650 is_detected<pointer_t, traits>::value &&
3651 is_detected<iterator_category_t, traits>::value &&
3652 is_detected<reference_t, traits>::value;
3655 template<typename T>
3659 using t_ref = typename std::add_lvalue_reference<T>::type;
3661 using iterator = detected_t<result_of_begin, t_ref>;
3662 using sentinel = detected_t<result_of_end, t_ref>;
3664 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3665 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3666 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3667 static constexpr auto is_iterator_begin =
3668 is_iterator_traits<iterator_traits<iterator>>::value;
3671 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3674 template<typename R>
3675 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3677 template<typename T>
3678 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3680 // The following implementation of is_complete_type is taken from
3681 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3682 // and is written by Xiang Fan who agreed to using it in this library.
3684 template<typename T, typename = void>
3685 struct is_complete_type : std::false_type {};
3687 template<typename T>
3688 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3690 template<typename BasicJsonType, typename CompatibleObjectType,
3692 struct is_compatible_object_type_impl : std::false_type {};
3694 template<typename BasicJsonType, typename CompatibleObjectType>
3695 struct is_compatible_object_type_impl <
3696 BasicJsonType, CompatibleObjectType,
3697 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3698 is_detected<key_type_t, CompatibleObjectType>::value >>
3700 using object_t = typename BasicJsonType::object_t;
3702 // macOS's is_constructible does not play well with nonesuch...
3703 static constexpr bool value =
3704 is_constructible<typename object_t::key_type,
3705 typename CompatibleObjectType::key_type>::value &&
3706 is_constructible<typename object_t::mapped_type,
3707 typename CompatibleObjectType::mapped_type>::value;
3710 template<typename BasicJsonType, typename CompatibleObjectType>
3711 struct is_compatible_object_type
3712 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3714 template<typename BasicJsonType, typename ConstructibleObjectType,
3716 struct is_constructible_object_type_impl : std::false_type {};
3718 template<typename BasicJsonType, typename ConstructibleObjectType>
3719 struct is_constructible_object_type_impl <
3720 BasicJsonType, ConstructibleObjectType,
3721 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3722 is_detected<key_type_t, ConstructibleObjectType>::value >>
3724 using object_t = typename BasicJsonType::object_t;
3726 static constexpr bool value =
3727 (is_default_constructible<ConstructibleObjectType>::value &&
3728 (std::is_move_assignable<ConstructibleObjectType>::value ||
3729 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3730 (is_constructible<typename ConstructibleObjectType::key_type,
3731 typename object_t::key_type>::value &&
3733 typename object_t::mapped_type,
3734 typename ConstructibleObjectType::mapped_type >::value)) ||
3735 (has_from_json<BasicJsonType,
3736 typename ConstructibleObjectType::mapped_type>::value ||
3737 has_non_default_from_json <
3739 typename ConstructibleObjectType::mapped_type >::value);
3742 template<typename BasicJsonType, typename ConstructibleObjectType>
3743 struct is_constructible_object_type
3744 : is_constructible_object_type_impl<BasicJsonType,
3745 ConstructibleObjectType> {};
3747 template<typename BasicJsonType, typename CompatibleStringType>
3748 struct is_compatible_string_type
3750 static constexpr auto value =
3751 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3754 template<typename BasicJsonType, typename ConstructibleStringType>
3755 struct is_constructible_string_type
3757 // launder type through decltype() to fix compilation failure on ICPC
3758 #ifdef __INTEL_COMPILER
3759 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3761 using laundered_type = ConstructibleStringType;
3764 static constexpr auto value =
3766 is_constructible<laundered_type, typename BasicJsonType::string_t>,
3767 is_detected_exact<typename BasicJsonType::string_t::value_type,
3768 value_type_t, laundered_type >>::value;
3771 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3772 struct is_compatible_array_type_impl : std::false_type {};
3774 template<typename BasicJsonType, typename CompatibleArrayType>
3775 struct is_compatible_array_type_impl <
3776 BasicJsonType, CompatibleArrayType,
3778 is_detected<iterator_t, CompatibleArrayType>::value&&
3779 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3780 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3781 // c.f. https://github.com/nlohmann/json/pull/3073
3782 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3784 static constexpr bool value =
3785 is_constructible<BasicJsonType,
3786 range_value_t<CompatibleArrayType>>::value;
3789 template<typename BasicJsonType, typename CompatibleArrayType>
3790 struct is_compatible_array_type
3791 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3793 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3794 struct is_constructible_array_type_impl : std::false_type {};
3796 template<typename BasicJsonType, typename ConstructibleArrayType>
3797 struct is_constructible_array_type_impl <
3798 BasicJsonType, ConstructibleArrayType,
3799 enable_if_t<std::is_same<ConstructibleArrayType,
3800 typename BasicJsonType::value_type>::value >>
3801 : std::true_type {};
3803 template<typename BasicJsonType, typename ConstructibleArrayType>
3804 struct is_constructible_array_type_impl <
3805 BasicJsonType, ConstructibleArrayType,
3806 enable_if_t < !std::is_same<ConstructibleArrayType,
3807 typename BasicJsonType::value_type>::value&&
3808 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3809 is_default_constructible<ConstructibleArrayType>::value&&
3810 (std::is_move_assignable<ConstructibleArrayType>::value ||
3811 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3812 is_detected<iterator_t, ConstructibleArrayType>::value&&
3813 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3814 is_detected<range_value_t, ConstructibleArrayType>::value&&
3815 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3816 // c.f. https://github.com/nlohmann/json/pull/3073
3817 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3819 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3821 using value_type = range_value_t<ConstructibleArrayType>;
3823 static constexpr bool value =
3824 std::is_same<value_type,
3825 typename BasicJsonType::array_t::value_type>::value ||
3826 has_from_json<BasicJsonType,
3827 value_type>::value ||
3828 has_non_default_from_json <
3830 value_type >::value;
3833 template<typename BasicJsonType, typename ConstructibleArrayType>
3834 struct is_constructible_array_type
3835 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3837 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3839 struct is_compatible_integer_type_impl : std::false_type {};
3841 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3842 struct is_compatible_integer_type_impl <
3843 RealIntegerType, CompatibleNumberIntegerType,
3844 enable_if_t < std::is_integral<RealIntegerType>::value&&
3845 std::is_integral<CompatibleNumberIntegerType>::value&&
3846 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3848 // is there an assert somewhere on overflows?
3849 using RealLimits = std::numeric_limits<RealIntegerType>;
3850 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3852 static constexpr auto value =
3853 is_constructible<RealIntegerType,
3854 CompatibleNumberIntegerType>::value &&
3855 CompatibleLimits::is_integer &&
3856 RealLimits::is_signed == CompatibleLimits::is_signed;
3859 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3860 struct is_compatible_integer_type
3861 : is_compatible_integer_type_impl<RealIntegerType,
3862 CompatibleNumberIntegerType> {};
3864 template<typename BasicJsonType, typename CompatibleType, typename = void>
3865 struct is_compatible_type_impl: std::false_type {};
3867 template<typename BasicJsonType, typename CompatibleType>
3868 struct is_compatible_type_impl <
3869 BasicJsonType, CompatibleType,
3870 enable_if_t<is_complete_type<CompatibleType>::value >>
3872 static constexpr bool value =
3873 has_to_json<BasicJsonType, CompatibleType>::value;
3876 template<typename BasicJsonType, typename CompatibleType>
3877 struct is_compatible_type
3878 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3880 template<typename T1, typename T2>
3881 struct is_constructible_tuple : std::false_type {};
3883 template<typename T1, typename... Args>
3884 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3886 template<typename BasicJsonType, typename T>
3887 struct is_json_iterator_of : std::false_type {};
3889 template<typename BasicJsonType>
3890 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3892 template<typename BasicJsonType>
3893 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3896 // checks if a given type T is a template specialization of Primary
3897 template<template <typename...> class Primary, typename T>
3898 struct is_specialization_of : std::false_type {};
3900 template<template <typename...> class Primary, typename... Args>
3901 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3903 template<typename T>
3904 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
3906 // checks if A and B are comparable using Compare functor
3907 template<typename Compare, typename A, typename B, typename = void>
3908 struct is_comparable : std::false_type {};
3910 template<typename Compare, typename A, typename B>
3911 struct is_comparable<Compare, A, B, void_t<
3912 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3913 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3914 >> : std::true_type {};
3916 template<typename T>
3917 using detect_is_transparent = typename T::is_transparent;
3919 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
3920 // see is_usable_as_basic_json_key_type below
3921 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3922 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3923 using is_usable_as_key_type = typename std::conditional <
3924 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
3925 && !(ExcludeObjectKeyType && std::is_same<KeyType,
3926 ObjectKeyType>::value)
3927 && (!RequireTransparentComparator
3928 || is_detected <detect_is_transparent, Comparator>::value)
3929 && !is_json_pointer<KeyType>::value,
3931 std::false_type >::type;
3933 // type trait to check if KeyType can be used as object key
3935 // - KeyType is comparable with BasicJsonType::object_t::key_type
3936 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
3937 // - the comparator is transparent or RequireTransparentComparator is false
3938 // - KeyType is not a JSON iterator or json_pointer
3939 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3940 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3941 using is_usable_as_basic_json_key_type = typename std::conditional <
3942 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
3943 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
3944 RequireTransparentComparator, ExcludeObjectKeyType>::value
3945 && !is_json_iterator_of<BasicJsonType, KeyType>::value,
3947 std::false_type >::type;
3949 template<typename ObjectType, typename KeyType>
3950 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
3952 // type trait to check if object_t has an erase() member functions accepting KeyType
3953 template<typename BasicJsonType, typename KeyType>
3954 using has_erase_with_key_type = typename std::conditional <
3956 detect_erase_with_key_type,
3957 typename BasicJsonType::object_t, KeyType >::value,
3959 std::false_type >::type;
3961 // a naive helper to check if a type is an ordered_map (exploits the fact that
3962 // ordered_map inherits capacity() from std::vector)
3963 template <typename T>
3964 struct is_ordered_map
3970 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
3973 template <typename C> static one test( decltype(&C::capacity) ) ;
3974 template <typename C> static two test(...);
3976 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
3979 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
3980 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
3981 T conditional_static_cast(U value)
3983 return static_cast<T>(value);
3986 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
3987 T conditional_static_cast(U value)
3992 template<typename... Types>
3993 using all_integral = conjunction<std::is_integral<Types>...>;
3995 template<typename... Types>
3996 using all_signed = conjunction<std::is_signed<Types>...>;
3998 template<typename... Types>
3999 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4001 // there's a disjunction trait in another PR; replace when merged
4002 template<typename... Types>
4003 using same_sign = std::integral_constant < bool,
4004 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4006 template<typename OfType, typename T>
4007 using never_out_of_range = std::integral_constant < bool,
4008 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4009 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4011 template<typename OfType, typename T,
4012 bool OfTypeSigned = std::is_signed<OfType>::value,
4013 bool TSigned = std::is_signed<T>::value>
4014 struct value_in_range_of_impl2;
4016 template<typename OfType, typename T>
4017 struct value_in_range_of_impl2<OfType, T, false, false>
4019 static constexpr bool test(T val)
4021 using CommonType = typename std::common_type<OfType, T>::type;
4022 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4026 template<typename OfType, typename T>
4027 struct value_in_range_of_impl2<OfType, T, true, false>
4029 static constexpr bool test(T val)
4031 using CommonType = typename std::common_type<OfType, T>::type;
4032 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4036 template<typename OfType, typename T>
4037 struct value_in_range_of_impl2<OfType, T, false, true>
4039 static constexpr bool test(T val)
4041 using CommonType = typename std::common_type<OfType, T>::type;
4042 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4047 template<typename OfType, typename T>
4048 struct value_in_range_of_impl2<OfType, T, true, true>
4050 static constexpr bool test(T val)
4052 using CommonType = typename std::common_type<OfType, T>::type;
4053 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4054 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4058 template<typename OfType, typename T,
4059 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4060 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4061 struct value_in_range_of_impl1;
4063 template<typename OfType, typename T>
4064 struct value_in_range_of_impl1<OfType, T, false>
4066 static constexpr bool test(T val)
4068 return value_in_range_of_impl2<OfType, T>::test(val);
4072 template<typename OfType, typename T>
4073 struct value_in_range_of_impl1<OfType, T, true>
4075 static constexpr bool test(T /*val*/)
4081 template<typename OfType, typename T>
4082 inline constexpr bool value_in_range_of(T val)
4084 return value_in_range_of_impl1<OfType, T>::test(val);
4087 template<bool Value>
4088 using bool_constant = std::integral_constant<bool, Value>;
4090 ///////////////////////////////////////////////////////////////////////////////
4092 ///////////////////////////////////////////////////////////////////////////////
4097 template<typename T>
4098 inline constexpr bool is_c_string()
4100 using TUnExt = typename std::remove_extent<T>::type;
4101 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4102 using TUnPtr = typename std::remove_pointer<T>::type;
4103 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4105 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4106 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4111 // checks whether T is a [cv] char */[cv] char[] C string
4112 template<typename T>
4113 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4115 template<typename T>
4116 using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4118 ///////////////////////////////////////////////////////////////////////////////
4120 ///////////////////////////////////////////////////////////////////////////////
4125 template<typename T>
4126 inline constexpr bool is_transparent()
4128 return is_detected<detect_is_transparent, T>::value;
4133 // checks whether T has a member named is_transparent
4134 template<typename T>
4135 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4137 ///////////////////////////////////////////////////////////////////////////////
4139 } // namespace detail
4140 NLOHMANN_JSON_NAMESPACE_END
4142 // #include <nlohmann/detail/string_concat.hpp>
4143 // __ _____ _____ _____
4144 // __| | __| | | | JSON for Modern C++
4145 // | | |__ | | | | | | version 3.11.2
4146 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
4148 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4149 // SPDX-License-Identifier: MIT
4153 #include <cstring> // strlen
4154 #include <string> // string
4155 #include <utility> // forward
4157 // #include <nlohmann/detail/meta/cpp_future.hpp>
4159 // #include <nlohmann/detail/meta/detected.hpp>
4162 NLOHMANN_JSON_NAMESPACE_BEGIN
4166 inline std::size_t concat_length()
4171 template<typename... Args>
4172 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4174 template<typename StringType, typename... Args>
4175 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4177 template<typename... Args>
4178 inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4180 return 1 + concat_length(rest...);
4183 template<typename... Args>
4184 inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4186 // cppcheck-suppress ignoredReturnValue
4187 return ::strlen(cstr) + concat_length(rest...);
4190 template<typename StringType, typename... Args>
4191 inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4193 return str.size() + concat_length(rest...);
4196 template<typename OutStringType>
4197 inline void concat_into(OutStringType& /*out*/)
4200 template<typename StringType, typename Arg>
4201 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4203 template<typename StringType, typename Arg>
4204 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4206 template<typename StringType, typename Arg>
4207 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4209 template<typename StringType, typename Arg>
4210 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4212 template<typename StringType, typename Arg>
4213 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4215 template<typename StringType, typename Arg>
4216 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4218 template<typename StringType, typename Arg>
4219 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4221 template<typename StringType, typename Arg>
4222 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4224 template < typename OutStringType, typename Arg, typename... Args,
4225 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4226 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4227 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4229 template < typename OutStringType, typename Arg, typename... Args,
4230 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4231 && !detect_string_can_append_op<OutStringType, Arg>::value
4232 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4233 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4235 template < typename OutStringType, typename Arg, typename... Args,
4236 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4237 && !detect_string_can_append_op<OutStringType, Arg>::value
4238 && !detect_string_can_append_iter<OutStringType, Arg>::value
4239 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4240 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4242 template<typename OutStringType, typename Arg, typename... Args,
4243 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4244 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4246 out.append(std::forward<Arg>(arg));
4247 concat_into(out, std::forward<Args>(rest)...);
4250 template < typename OutStringType, typename Arg, typename... Args,
4251 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4252 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4253 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4255 out += std::forward<Arg>(arg);
4256 concat_into(out, std::forward<Args>(rest)...);
4259 template < typename OutStringType, typename Arg, typename... Args,
4260 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4261 && !detect_string_can_append_op<OutStringType, Arg>::value
4262 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4263 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4265 out.append(arg.begin(), arg.end());
4266 concat_into(out, std::forward<Args>(rest)...);
4269 template < typename OutStringType, typename Arg, typename... Args,
4270 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4271 && !detect_string_can_append_op<OutStringType, Arg>::value
4272 && !detect_string_can_append_iter<OutStringType, Arg>::value
4273 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4274 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4276 out.append(arg.data(), arg.size());
4277 concat_into(out, std::forward<Args>(rest)...);
4280 template<typename OutStringType = std::string, typename... Args>
4281 inline OutStringType concat(Args && ... args)
4284 str.reserve(concat_length(args...));
4285 concat_into(str, std::forward<Args>(args)...);
4289 } // namespace detail
4290 NLOHMANN_JSON_NAMESPACE_END
4294 NLOHMANN_JSON_NAMESPACE_BEGIN
4302 /// @brief general exception of the @ref basic_json class
4303 /// @sa https://json.nlohmann.me/api/basic_json/exception/
4304 class exception : public std::exception
4307 /// returns the explanatory string
4308 const char* what() const noexcept override
4313 /// the id of the exception
4314 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4317 JSON_HEDLEY_NON_NULL(3)
4318 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4320 static std::string name(const std::string& ename, int id_)
4322 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4325 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4330 template<typename BasicJsonType>
4331 static std::string diagnostics(const BasicJsonType* leaf_element)
4333 #if JSON_DIAGNOSTICS
4334 std::vector<std::string> tokens;
4335 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4337 switch (current->m_parent->type())
4339 case value_t::array:
4341 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4343 if (¤t->m_parent->m_data.m_value.array->operator[](i) == current)
4345 tokens.emplace_back(std::to_string(i));
4352 case value_t::object:
4354 for (const auto& element : *current->m_parent->m_data.m_value.object)
4356 if (&element.second == current)
4358 tokens.emplace_back(element.first.c_str());
4365 case value_t::null: // LCOV_EXCL_LINE
4366 case value_t::string: // LCOV_EXCL_LINE
4367 case value_t::boolean: // LCOV_EXCL_LINE
4368 case value_t::number_integer: // LCOV_EXCL_LINE
4369 case value_t::number_unsigned: // LCOV_EXCL_LINE
4370 case value_t::number_float: // LCOV_EXCL_LINE
4371 case value_t::binary: // LCOV_EXCL_LINE
4372 case value_t::discarded: // LCOV_EXCL_LINE
4373 default: // LCOV_EXCL_LINE
4374 break; // LCOV_EXCL_LINE
4383 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4384 [](const std::string & a, const std::string & b)
4386 return concat(a, '/', detail::escape(b));
4388 return concat('(', str, ") ");
4390 static_cast<void>(leaf_element);
4396 /// an exception object as storage for error messages
4397 std::runtime_error m;
4400 /// @brief exception indicating a parse error
4401 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4402 class parse_error : public exception
4406 @brief create a parse error exception
4407 @param[in] id_ the id of the exception
4408 @param[in] pos the position where the error occurred (or with
4409 chars_read_total=0 if the position cannot be
4411 @param[in] what_arg the explanatory string
4412 @return parse_error object
4414 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4415 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4417 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4418 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4419 return {id_, pos.chars_read_total, w.c_str()};
4422 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4423 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4425 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4426 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4427 ": ", exception::diagnostics(context), what_arg);
4428 return {id_, byte_, w.c_str()};
4432 @brief byte index of the parse error
4434 The byte index of the last read character in the input file.
4436 @note For an input with n bytes, 1 is the index of the first character and
4437 n+1 is the index of the terminating null byte or the end of file.
4438 This also holds true when reading a byte vector (CBOR or MessagePack).
4440 const std::size_t byte;
4443 parse_error(int id_, std::size_t byte_, const char* what_arg)
4444 : exception(id_, what_arg), byte(byte_) {}
4446 static std::string position_string(const position_t& pos)
4448 return concat(" at line ", std::to_string(pos.lines_read + 1),
4449 ", column ", std::to_string(pos.chars_read_current_line));
4453 /// @brief exception indicating errors with iterators
4454 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4455 class invalid_iterator : public exception
4458 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4459 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4461 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4462 return {id_, w.c_str()};
4466 JSON_HEDLEY_NON_NULL(3)
4467 invalid_iterator(int id_, const char* what_arg)
4468 : exception(id_, what_arg) {}
4471 /// @brief exception indicating executing a member function with a wrong type
4472 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
4473 class type_error : public exception
4476 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4477 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4479 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4480 return {id_, w.c_str()};
4484 JSON_HEDLEY_NON_NULL(3)
4485 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4488 /// @brief exception indicating access out of the defined range
4489 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4490 class out_of_range : public exception
4493 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4494 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4496 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4497 return {id_, w.c_str()};
4501 JSON_HEDLEY_NON_NULL(3)
4502 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4505 /// @brief exception indicating other library errors
4506 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
4507 class other_error : public exception
4510 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4511 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4513 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4514 return {id_, w.c_str()};
4518 JSON_HEDLEY_NON_NULL(3)
4519 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4522 } // namespace detail
4523 NLOHMANN_JSON_NAMESPACE_END
4525 // #include <nlohmann/detail/macro_scope.hpp>
4527 // #include <nlohmann/detail/meta/cpp_future.hpp>
4529 // #include <nlohmann/detail/meta/identity_tag.hpp>
4530 // __ _____ _____ _____
4531 // __| | __| | | | JSON for Modern C++
4532 // | | |__ | | | | | | version 3.11.2
4533 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
4535 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4536 // SPDX-License-Identifier: MIT
4540 // #include <nlohmann/detail/abi_macros.hpp>
4543 NLOHMANN_JSON_NAMESPACE_BEGIN
4547 // dispatching helper struct
4548 template <class T> struct identity_tag {};
4550 } // namespace detail
4551 NLOHMANN_JSON_NAMESPACE_END
4553 // #include <nlohmann/detail/meta/std_fs.hpp>
4554 // __ _____ _____ _____
4555 // __| | __| | | | JSON for Modern C++
4556 // | | |__ | | | | | | version 3.11.2
4557 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
4559 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
4560 // SPDX-License-Identifier: MIT
4564 // #include <nlohmann/detail/macro_scope.hpp>
4567 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4568 #include <experimental/filesystem>
4569 NLOHMANN_JSON_NAMESPACE_BEGIN
4572 namespace std_fs = std::experimental::filesystem;
4573 } // namespace detail
4574 NLOHMANN_JSON_NAMESPACE_END
4575 #elif JSON_HAS_FILESYSTEM
4576 #include <filesystem>
4577 NLOHMANN_JSON_NAMESPACE_BEGIN
4580 namespace std_fs = std::filesystem;
4581 } // namespace detail
4582 NLOHMANN_JSON_NAMESPACE_END
4585 // #include <nlohmann/detail/meta/type_traits.hpp>
4587 // #include <nlohmann/detail/string_concat.hpp>
4589 // #include <nlohmann/detail/value_t.hpp>
4592 NLOHMANN_JSON_NAMESPACE_BEGIN
4596 template<typename BasicJsonType>
4597 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4599 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4601 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4606 // overloads for basic_json template parameters
4607 template < typename BasicJsonType, typename ArithmeticType,
4608 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4609 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4611 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4613 switch (static_cast<value_t>(j))
4615 case value_t::number_unsigned:
4617 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4620 case value_t::number_integer:
4622 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4625 case value_t::number_float:
4627 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4632 case value_t::object:
4633 case value_t::array:
4634 case value_t::string:
4635 case value_t::boolean:
4636 case value_t::binary:
4637 case value_t::discarded:
4639 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4643 template<typename BasicJsonType>
4644 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4646 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4648 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4650 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4653 template<typename BasicJsonType>
4654 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4656 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4658 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4660 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4664 typename BasicJsonType, typename StringType,
4666 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4667 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4668 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4669 && !is_json_ref<StringType>::value, int > = 0 >
4670 inline void from_json(const BasicJsonType& j, StringType& s)
4672 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4674 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4677 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4680 template<typename BasicJsonType>
4681 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4683 get_arithmetic_value(j, val);
4686 template<typename BasicJsonType>
4687 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4689 get_arithmetic_value(j, val);
4692 template<typename BasicJsonType>
4693 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4695 get_arithmetic_value(j, val);
4698 #if !JSON_DISABLE_ENUM_SERIALIZATION
4699 template<typename BasicJsonType, typename EnumType,
4700 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4701 inline void from_json(const BasicJsonType& j, EnumType& e)
4703 typename std::underlying_type<EnumType>::type val;
4704 get_arithmetic_value(j, val);
4705 e = static_cast<EnumType>(val);
4707 #endif // JSON_DISABLE_ENUM_SERIALIZATION
4709 // forward_list doesn't have an insert method
4710 template<typename BasicJsonType, typename T, typename Allocator,
4711 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4712 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4714 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4716 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4719 std::transform(j.rbegin(), j.rend(),
4720 std::front_inserter(l), [](const BasicJsonType & i)
4722 return i.template get<T>();
4726 // valarray doesn't have an insert method
4727 template<typename BasicJsonType, typename T,
4728 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4729 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4731 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4733 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4736 std::transform(j.begin(), j.end(), std::begin(l),
4737 [](const BasicJsonType & elem)
4739 return elem.template get<T>();
4743 template<typename BasicJsonType, typename T, std::size_t N>
4744 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4745 -> decltype(j.template get<T>(), void())
4747 for (std::size_t i = 0; i < N; ++i)
4749 arr[i] = j.at(i).template get<T>();
4753 template<typename BasicJsonType>
4754 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4756 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4759 template<typename BasicJsonType, typename T, std::size_t N>
4760 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4761 priority_tag<2> /*unused*/)
4762 -> decltype(j.template get<T>(), void())
4764 for (std::size_t i = 0; i < N; ++i)
4766 arr[i] = j.at(i).template get<T>();
4770 template<typename BasicJsonType, typename ConstructibleArrayType,
4772 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4774 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4776 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4777 j.template get<typename ConstructibleArrayType::value_type>(),
4782 ConstructibleArrayType ret;
4783 ret.reserve(j.size());
4784 std::transform(j.begin(), j.end(),
4785 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4787 // get<BasicJsonType>() returns *this, this won't call a from_json
4788 // method when value_type is BasicJsonType
4789 return i.template get<typename ConstructibleArrayType::value_type>();
4791 arr = std::move(ret);
4794 template<typename BasicJsonType, typename ConstructibleArrayType,
4796 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4798 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4799 priority_tag<0> /*unused*/)
4803 ConstructibleArrayType ret;
4805 j.begin(), j.end(), std::inserter(ret, end(ret)),
4806 [](const BasicJsonType & i)
4808 // get<BasicJsonType>() returns *this, this won't call a from_json
4809 // method when value_type is BasicJsonType
4810 return i.template get<typename ConstructibleArrayType::value_type>();
4812 arr = std::move(ret);
4815 template < typename BasicJsonType, typename ConstructibleArrayType,
4817 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4818 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4819 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4820 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4821 !is_basic_json<ConstructibleArrayType>::value,
4823 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4824 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4825 j.template get<typename ConstructibleArrayType::value_type>(),
4828 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4830 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4833 from_json_array_impl(j, arr, priority_tag<3> {});
4836 template < typename BasicJsonType, typename T, std::size_t... Idx >
4837 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4838 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4840 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4843 template < typename BasicJsonType, typename T, std::size_t N >
4844 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4845 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4847 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4849 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4852 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4855 template<typename BasicJsonType>
4856 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4858 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4860 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4863 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4866 template<typename BasicJsonType, typename ConstructibleObjectType,
4867 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4868 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4870 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4872 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4875 ConstructibleObjectType ret;
4876 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4877 using value_type = typename ConstructibleObjectType::value_type;
4879 inner_object->begin(), inner_object->end(),
4880 std::inserter(ret, ret.begin()),
4881 [](typename BasicJsonType::object_t::value_type const & p)
4883 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4885 obj = std::move(ret);
4888 // overload for arithmetic types, not chosen for basic_json template arguments
4889 // (BooleanType, etc..); note: Is it really necessary to provide explicit
4890 // overloads for boolean_t etc. in case of a custom BooleanType which is not
4891 // an arithmetic type?
4892 template < typename BasicJsonType, typename ArithmeticType,
4894 std::is_arithmetic<ArithmeticType>::value&&
4895 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4896 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4897 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4898 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4900 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4902 switch (static_cast<value_t>(j))
4904 case value_t::number_unsigned:
4906 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4909 case value_t::number_integer:
4911 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4914 case value_t::number_float:
4916 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4919 case value_t::boolean:
4921 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4926 case value_t::object:
4927 case value_t::array:
4928 case value_t::string:
4929 case value_t::binary:
4930 case value_t::discarded:
4932 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4936 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
4937 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
4939 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
4942 template < typename BasicJsonType, class A1, class A2 >
4943 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
4945 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
4946 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
4949 template<typename BasicJsonType, typename A1, typename A2>
4950 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
4952 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
4955 template<typename BasicJsonType, typename... Args>
4956 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
4958 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4961 template<typename BasicJsonType, typename... Args>
4962 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
4964 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
4967 template<typename BasicJsonType, typename TupleRelated>
4968 auto from_json(BasicJsonType&& j, TupleRelated&& t)
4969 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
4971 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4973 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4976 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
4979 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
4980 typename = enable_if_t < !std::is_constructible <
4981 typename BasicJsonType::string_t, Key >::value >>
4982 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
4984 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4986 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4989 for (const auto& p : j)
4991 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
4993 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
4995 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
4999 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5000 typename = enable_if_t < !std::is_constructible <
5001 typename BasicJsonType::string_t, Key >::value >>
5002 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5004 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5006 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5009 for (const auto& p : j)
5011 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5013 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5015 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5019 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5020 template<typename BasicJsonType>
5021 inline void from_json(const BasicJsonType& j, std_fs::path& p)
5023 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5025 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5027 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5033 template<typename BasicJsonType, typename T>
5034 auto operator()(const BasicJsonType& j, T&& val) const
5035 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5036 -> decltype(from_json(j, std::forward<T>(val)))
5038 return from_json(j, std::forward<T>(val));
5042 } // namespace detail
5044 #ifndef JSON_HAS_CPP_17
5045 /// namespace to hold default `from_json` function
5046 /// to see why this is required:
5047 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5048 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5051 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5052 detail::static_const<detail::from_json_fn>::value;
5053 #ifndef JSON_HAS_CPP_17
5057 NLOHMANN_JSON_NAMESPACE_END
5059 // #include <nlohmann/detail/conversions/to_json.hpp>
5060 // __ _____ _____ _____
5061 // __| | __| | | | JSON for Modern C++
5062 // | | |__ | | | | | | version 3.11.2
5063 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5065 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5066 // SPDX-License-Identifier: MIT
5070 #include <algorithm> // copy
5071 #include <iterator> // begin, end
5072 #include <string> // string
5073 #include <tuple> // tuple, get
5074 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5075 #include <utility> // move, forward, declval, pair
5076 #include <valarray> // valarray
5077 #include <vector> // vector
5079 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5080 // __ _____ _____ _____
5081 // __| | __| | | | JSON for Modern C++
5082 // | | |__ | | | | | | version 3.11.2
5083 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5085 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5086 // SPDX-License-Identifier: MIT
5090 #include <cstddef> // size_t
5091 #include <iterator> // input_iterator_tag
5092 #include <string> // string, to_string
5093 #include <tuple> // tuple_size, get, tuple_element
5094 #include <utility> // move
5097 #include <ranges> // enable_borrowed_range
5100 // #include <nlohmann/detail/abi_macros.hpp>
5102 // #include <nlohmann/detail/meta/type_traits.hpp>
5104 // #include <nlohmann/detail/value_t.hpp>
5107 NLOHMANN_JSON_NAMESPACE_BEGIN
5111 template<typename string_type>
5112 void int_to_string( string_type& target, std::size_t value )
5115 using std::to_string;
5116 target = to_string(value);
5118 template<typename IteratorType> class iteration_proxy_value
5121 using difference_type = std::ptrdiff_t;
5122 using value_type = iteration_proxy_value;
5123 using pointer = value_type *;
5124 using reference = value_type &;
5125 using iterator_category = std::input_iterator_tag;
5126 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5130 IteratorType anchor{};
5131 /// an index for arrays (used to create key names)
5132 std::size_t array_index = 0;
5133 /// last stringified array index
5134 mutable std::size_t array_index_last = 0;
5135 /// a string representation of the array index
5136 mutable string_type array_index_str = "0";
5137 /// an empty string (to return a reference for primitive values)
5138 string_type empty_str{};
5141 explicit iteration_proxy_value() = default;
5142 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5143 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5144 && std::is_nothrow_default_constructible<string_type>::value)
5145 : anchor(std::move(it))
5146 , array_index(array_index_)
5149 iteration_proxy_value(iteration_proxy_value const&) = default;
5150 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5151 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5152 iteration_proxy_value(iteration_proxy_value&&)
5153 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5154 && std::is_nothrow_move_constructible<string_type>::value) = default;
5155 iteration_proxy_value& operator=(iteration_proxy_value&&)
5156 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5157 && std::is_nothrow_move_assignable<string_type>::value) = default;
5158 ~iteration_proxy_value() = default;
5160 /// dereference operator (needed for range-based for)
5161 const iteration_proxy_value& operator*() const
5166 /// increment operator (needed for range-based for)
5167 iteration_proxy_value& operator++()
5175 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5177 auto tmp = iteration_proxy_value(anchor, array_index);
5183 /// equality operator (needed for InputIterator)
5184 bool operator==(const iteration_proxy_value& o) const
5186 return anchor == o.anchor;
5189 /// inequality operator (needed for range-based for)
5190 bool operator!=(const iteration_proxy_value& o) const
5192 return anchor != o.anchor;
5195 /// return key of the iterator
5196 const string_type& key() const
5198 JSON_ASSERT(anchor.m_object != nullptr);
5200 switch (anchor.m_object->type())
5202 // use integer array index as key
5203 case value_t::array:
5205 if (array_index != array_index_last)
5207 int_to_string( array_index_str, array_index );
5208 array_index_last = array_index;
5210 return array_index_str;
5213 // use key from the object
5214 case value_t::object:
5215 return anchor.key();
5217 // use an empty key for all primitive types
5219 case value_t::string:
5220 case value_t::boolean:
5221 case value_t::number_integer:
5222 case value_t::number_unsigned:
5223 case value_t::number_float:
5224 case value_t::binary:
5225 case value_t::discarded:
5231 /// return value of the iterator
5232 typename IteratorType::reference value() const
5234 return anchor.value();
5238 /// proxy class for the items() function
5239 template<typename IteratorType> class iteration_proxy
5242 /// the container to iterate
5243 typename IteratorType::pointer container = nullptr;
5246 explicit iteration_proxy() = default;
5248 /// construct iteration proxy from a container
5249 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5250 : container(&cont) {}
5252 iteration_proxy(iteration_proxy const&) = default;
5253 iteration_proxy& operator=(iteration_proxy const&) = default;
5254 iteration_proxy(iteration_proxy&&) noexcept = default;
5255 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5256 ~iteration_proxy() = default;
5258 /// return iterator begin (needed for range-based for)
5259 iteration_proxy_value<IteratorType> begin() const noexcept
5261 return iteration_proxy_value<IteratorType>(container->begin());
5264 /// return iterator end (needed for range-based for)
5265 iteration_proxy_value<IteratorType> end() const noexcept
5267 return iteration_proxy_value<IteratorType>(container->end());
5271 // Structured Bindings Support
5272 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5273 // And see https://github.com/nlohmann/json/pull/1391
5274 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5275 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5279 // Structured Bindings Support
5280 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5281 // And see https://github.com/nlohmann/json/pull/1391
5282 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5283 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5288 } // namespace detail
5289 NLOHMANN_JSON_NAMESPACE_END
5291 // The Addition to the STD Namespace is required to add
5292 // Structured Bindings Support to the iteration_proxy_value class
5293 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5294 // And see https://github.com/nlohmann/json/pull/1391
5298 #if defined(__clang__)
5299 // Fix: https://github.com/nlohmann/json/issues/1401
5300 #pragma clang diagnostic push
5301 #pragma clang diagnostic ignored "-Wmismatched-tags"
5303 template<typename IteratorType>
5304 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5305 : public std::integral_constant<std::size_t, 2> {};
5307 template<std::size_t N, typename IteratorType>
5308 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5311 using type = decltype(
5312 get<N>(std::declval <
5313 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5315 #if defined(__clang__)
5316 #pragma clang diagnostic pop
5322 template <typename IteratorType>
5323 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5326 // #include <nlohmann/detail/macro_scope.hpp>
5328 // #include <nlohmann/detail/meta/cpp_future.hpp>
5330 // #include <nlohmann/detail/meta/std_fs.hpp>
5332 // #include <nlohmann/detail/meta/type_traits.hpp>
5334 // #include <nlohmann/detail/value_t.hpp>
5337 NLOHMANN_JSON_NAMESPACE_BEGIN
5346 * Note all external_constructor<>::construct functions need to call
5347 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5348 * allocated value (e.g., a string). See bug issue
5349 * https://github.com/nlohmann/json/issues/2865 for more information.
5352 template<value_t> struct external_constructor;
5355 struct external_constructor<value_t::boolean>
5357 template<typename BasicJsonType>
5358 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5360 j.m_data.m_value.destroy(j.m_data.m_type);
5361 j.m_data.m_type = value_t::boolean;
5362 j.m_data.m_value = b;
5363 j.assert_invariant();
5368 struct external_constructor<value_t::string>
5370 template<typename BasicJsonType>
5371 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5373 j.m_data.m_value.destroy(j.m_data.m_type);
5374 j.m_data.m_type = value_t::string;
5375 j.m_data.m_value = s;
5376 j.assert_invariant();
5379 template<typename BasicJsonType>
5380 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5382 j.m_data.m_value.destroy(j.m_data.m_type);
5383 j.m_data.m_type = value_t::string;
5384 j.m_data.m_value = std::move(s);
5385 j.assert_invariant();
5388 template < typename BasicJsonType, typename CompatibleStringType,
5389 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5391 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5393 j.m_data.m_value.destroy(j.m_data.m_type);
5394 j.m_data.m_type = value_t::string;
5395 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5396 j.assert_invariant();
5401 struct external_constructor<value_t::binary>
5403 template<typename BasicJsonType>
5404 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5406 j.m_data.m_value.destroy(j.m_data.m_type);
5407 j.m_data.m_type = value_t::binary;
5408 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5409 j.assert_invariant();
5412 template<typename BasicJsonType>
5413 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5415 j.m_data.m_value.destroy(j.m_data.m_type);
5416 j.m_data.m_type = value_t::binary;
5417 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5418 j.assert_invariant();
5423 struct external_constructor<value_t::number_float>
5425 template<typename BasicJsonType>
5426 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5428 j.m_data.m_value.destroy(j.m_data.m_type);
5429 j.m_data.m_type = value_t::number_float;
5430 j.m_data.m_value = val;
5431 j.assert_invariant();
5436 struct external_constructor<value_t::number_unsigned>
5438 template<typename BasicJsonType>
5439 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5441 j.m_data.m_value.destroy(j.m_data.m_type);
5442 j.m_data.m_type = value_t::number_unsigned;
5443 j.m_data.m_value = val;
5444 j.assert_invariant();
5449 struct external_constructor<value_t::number_integer>
5451 template<typename BasicJsonType>
5452 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5454 j.m_data.m_value.destroy(j.m_data.m_type);
5455 j.m_data.m_type = value_t::number_integer;
5456 j.m_data.m_value = val;
5457 j.assert_invariant();
5462 struct external_constructor<value_t::array>
5464 template<typename BasicJsonType>
5465 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5467 j.m_data.m_value.destroy(j.m_data.m_type);
5468 j.m_data.m_type = value_t::array;
5469 j.m_data.m_value = arr;
5471 j.assert_invariant();
5474 template<typename BasicJsonType>
5475 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5477 j.m_data.m_value.destroy(j.m_data.m_type);
5478 j.m_data.m_type = value_t::array;
5479 j.m_data.m_value = std::move(arr);
5481 j.assert_invariant();
5484 template < typename BasicJsonType, typename CompatibleArrayType,
5485 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5487 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5492 j.m_data.m_value.destroy(j.m_data.m_type);
5493 j.m_data.m_type = value_t::array;
5494 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5496 j.assert_invariant();
5499 template<typename BasicJsonType>
5500 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5502 j.m_data.m_value.destroy(j.m_data.m_type);
5503 j.m_data.m_type = value_t::array;
5504 j.m_data.m_value = value_t::array;
5505 j.m_data.m_value.array->reserve(arr.size());
5506 for (const bool x : arr)
5508 j.m_data.m_value.array->push_back(x);
5509 j.set_parent(j.m_data.m_value.array->back());
5511 j.assert_invariant();
5514 template<typename BasicJsonType, typename T,
5515 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5516 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5518 j.m_data.m_value.destroy(j.m_data.m_type);
5519 j.m_data.m_type = value_t::array;
5520 j.m_data.m_value = value_t::array;
5521 j.m_data.m_value.array->resize(arr.size());
5524 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5527 j.assert_invariant();
5532 struct external_constructor<value_t::object>
5534 template<typename BasicJsonType>
5535 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5537 j.m_data.m_value.destroy(j.m_data.m_type);
5538 j.m_data.m_type = value_t::object;
5539 j.m_data.m_value = obj;
5541 j.assert_invariant();
5544 template<typename BasicJsonType>
5545 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5547 j.m_data.m_value.destroy(j.m_data.m_type);
5548 j.m_data.m_type = value_t::object;
5549 j.m_data.m_value = std::move(obj);
5551 j.assert_invariant();
5554 template < typename BasicJsonType, typename CompatibleObjectType,
5555 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5556 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5561 j.m_data.m_value.destroy(j.m_data.m_type);
5562 j.m_data.m_type = value_t::object;
5563 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5565 j.assert_invariant();
5573 template<typename BasicJsonType, typename T,
5574 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5575 inline void to_json(BasicJsonType& j, T b) noexcept
5577 external_constructor<value_t::boolean>::construct(j, b);
5580 template < typename BasicJsonType, typename BoolRef,
5582 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5583 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5584 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5585 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5586 typename BasicJsonType::boolean_t >::value))
5587 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5588 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5590 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5593 template<typename BasicJsonType, typename CompatibleString,
5594 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5595 inline void to_json(BasicJsonType& j, const CompatibleString& s)
5597 external_constructor<value_t::string>::construct(j, s);
5600 template<typename BasicJsonType>
5601 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5603 external_constructor<value_t::string>::construct(j, std::move(s));
5606 template<typename BasicJsonType, typename FloatType,
5607 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5608 inline void to_json(BasicJsonType& j, FloatType val) noexcept
5610 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5613 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5614 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5615 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5617 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5620 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5621 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5622 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5624 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5627 #if !JSON_DISABLE_ENUM_SERIALIZATION
5628 template<typename BasicJsonType, typename EnumType,
5629 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5630 inline void to_json(BasicJsonType& j, EnumType e) noexcept
5632 using underlying_type = typename std::underlying_type<EnumType>::type;
5633 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5635 #endif // JSON_DISABLE_ENUM_SERIALIZATION
5637 template<typename BasicJsonType>
5638 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5640 external_constructor<value_t::array>::construct(j, e);
5643 template < typename BasicJsonType, typename CompatibleArrayType,
5644 enable_if_t < is_compatible_array_type<BasicJsonType,
5645 CompatibleArrayType>::value&&
5646 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5647 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5648 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5649 !is_basic_json<CompatibleArrayType>::value,
5651 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5653 external_constructor<value_t::array>::construct(j, arr);
5656 template<typename BasicJsonType>
5657 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5659 external_constructor<value_t::binary>::construct(j, bin);
5662 template<typename BasicJsonType, typename T,
5663 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5664 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5666 external_constructor<value_t::array>::construct(j, std::move(arr));
5669 template<typename BasicJsonType>
5670 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5672 external_constructor<value_t::array>::construct(j, std::move(arr));
5675 template < typename BasicJsonType, typename CompatibleObjectType,
5676 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5677 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5679 external_constructor<value_t::object>::construct(j, obj);
5682 template<typename BasicJsonType>
5683 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5685 external_constructor<value_t::object>::construct(j, std::move(obj));
5689 typename BasicJsonType, typename T, std::size_t N,
5690 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5691 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5693 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5695 external_constructor<value_t::array>::construct(j, arr);
5698 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5699 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5701 j = { p.first, p.second };
5704 // for https://github.com/nlohmann/json/pull/1134
5705 template<typename BasicJsonType, typename T,
5706 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5707 inline void to_json(BasicJsonType& j, const T& b)
5709 j = { {b.key(), b.value()} };
5712 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5713 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5715 j = { std::get<Idx>(t)... };
5718 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5719 inline void to_json(BasicJsonType& j, const T& t)
5721 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5724 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5725 template<typename BasicJsonType>
5726 inline void to_json(BasicJsonType& j, const std_fs::path& p)
5734 template<typename BasicJsonType, typename T>
5735 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5736 -> decltype(to_json(j, std::forward<T>(val)), void())
5738 return to_json(j, std::forward<T>(val));
5741 } // namespace detail
5743 #ifndef JSON_HAS_CPP_17
5744 /// namespace to hold default `to_json` function
5745 /// to see why this is required:
5746 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5747 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5750 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5751 detail::static_const<detail::to_json_fn>::value;
5752 #ifndef JSON_HAS_CPP_17
5756 NLOHMANN_JSON_NAMESPACE_END
5758 // #include <nlohmann/detail/meta/identity_tag.hpp>
5761 NLOHMANN_JSON_NAMESPACE_BEGIN
5763 /// @sa https://json.nlohmann.me/api/adl_serializer/
5764 template<typename ValueType, typename>
5765 struct adl_serializer
5767 /// @brief convert a JSON value to any value type
5768 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5769 template<typename BasicJsonType, typename TargetType = ValueType>
5770 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5771 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5772 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5774 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5777 /// @brief convert a JSON value to any value type
5778 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5779 template<typename BasicJsonType, typename TargetType = ValueType>
5780 static auto from_json(BasicJsonType && j) noexcept(
5781 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5782 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5784 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5787 /// @brief convert any value type to a JSON value
5788 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
5789 template<typename BasicJsonType, typename TargetType = ValueType>
5790 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5791 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5792 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5794 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5798 NLOHMANN_JSON_NAMESPACE_END
5800 // #include <nlohmann/byte_container_with_subtype.hpp>
5801 // __ _____ _____ _____
5802 // __| | __| | | | JSON for Modern C++
5803 // | | |__ | | | | | | version 3.11.2
5804 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5806 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5807 // SPDX-License-Identifier: MIT
5811 #include <cstdint> // uint8_t, uint64_t
5812 #include <tuple> // tie
5813 #include <utility> // move
5815 // #include <nlohmann/detail/abi_macros.hpp>
5818 NLOHMANN_JSON_NAMESPACE_BEGIN
5820 /// @brief an internal type for a backed binary type
5821 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
5822 template<typename BinaryType>
5823 class byte_container_with_subtype : public BinaryType
5826 using container_type = BinaryType;
5827 using subtype_type = std::uint64_t;
5829 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5830 byte_container_with_subtype() noexcept(noexcept(container_type()))
5834 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5835 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5839 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5840 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5841 : container_type(std::move(b))
5844 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5845 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5847 , m_subtype(subtype_)
5848 , m_has_subtype(true)
5851 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5852 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5853 : container_type(std::move(b))
5854 , m_subtype(subtype_)
5855 , m_has_subtype(true)
5858 bool operator==(const byte_container_with_subtype& rhs) const
5860 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5861 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5864 bool operator!=(const byte_container_with_subtype& rhs) const
5866 return !(rhs == *this);
5869 /// @brief sets the binary subtype
5870 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
5871 void set_subtype(subtype_type subtype_) noexcept
5873 m_subtype = subtype_;
5874 m_has_subtype = true;
5877 /// @brief return the binary subtype
5878 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
5879 constexpr subtype_type subtype() const noexcept
5881 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5884 /// @brief return whether the value has a subtype
5885 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
5886 constexpr bool has_subtype() const noexcept
5888 return m_has_subtype;
5891 /// @brief clears the binary subtype
5892 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
5893 void clear_subtype() noexcept
5896 m_has_subtype = false;
5900 subtype_type m_subtype = 0;
5901 bool m_has_subtype = false;
5904 NLOHMANN_JSON_NAMESPACE_END
5906 // #include <nlohmann/detail/conversions/from_json.hpp>
5908 // #include <nlohmann/detail/conversions/to_json.hpp>
5910 // #include <nlohmann/detail/exceptions.hpp>
5912 // #include <nlohmann/detail/hash.hpp>
5913 // __ _____ _____ _____
5914 // __| | __| | | | JSON for Modern C++
5915 // | | |__ | | | | | | version 3.11.2
5916 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5918 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
5919 // SPDX-License-Identifier: MIT
5923 #include <cstdint> // uint8_t
5924 #include <cstddef> // size_t
5925 #include <functional> // hash
5927 // #include <nlohmann/detail/abi_macros.hpp>
5929 // #include <nlohmann/detail/value_t.hpp>
5932 NLOHMANN_JSON_NAMESPACE_BEGIN
5936 // boost::hash_combine
5937 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
5939 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
5944 @brief hash a JSON value
5946 The hash function tries to rely on std::hash where possible. Furthermore, the
5947 type of the JSON value is taken into account to have different hash values for
5948 null, 0, 0U, and false, etc.
5950 @tparam BasicJsonType basic_json specialization
5951 @param j JSON value to hash
5952 @return hash value of j
5954 template<typename BasicJsonType>
5955 std::size_t hash(const BasicJsonType& j)
5957 using string_t = typename BasicJsonType::string_t;
5958 using number_integer_t = typename BasicJsonType::number_integer_t;
5959 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
5960 using number_float_t = typename BasicJsonType::number_float_t;
5962 const auto type = static_cast<std::size_t>(j.type());
5965 case BasicJsonType::value_t::null:
5966 case BasicJsonType::value_t::discarded:
5968 return combine(type, 0);
5971 case BasicJsonType::value_t::object:
5973 auto seed = combine(type, j.size());
5974 for (const auto& element : j.items())
5976 const auto h = std::hash<string_t> {}(element.key());
5977 seed = combine(seed, h);
5978 seed = combine(seed, hash(element.value()));
5983 case BasicJsonType::value_t::array:
5985 auto seed = combine(type, j.size());
5986 for (const auto& element : j)
5988 seed = combine(seed, hash(element));
5993 case BasicJsonType::value_t::string:
5995 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
5996 return combine(type, h);
5999 case BasicJsonType::value_t::boolean:
6001 const auto h = std::hash<bool> {}(j.template get<bool>());
6002 return combine(type, h);
6005 case BasicJsonType::value_t::number_integer:
6007 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6008 return combine(type, h);
6011 case BasicJsonType::value_t::number_unsigned:
6013 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6014 return combine(type, h);
6017 case BasicJsonType::value_t::number_float:
6019 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6020 return combine(type, h);
6023 case BasicJsonType::value_t::binary:
6025 auto seed = combine(type, j.get_binary().size());
6026 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6027 seed = combine(seed, h);
6028 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6029 for (const auto byte : j.get_binary())
6031 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6036 default: // LCOV_EXCL_LINE
6037 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6038 return 0; // LCOV_EXCL_LINE
6042 } // namespace detail
6043 NLOHMANN_JSON_NAMESPACE_END
6045 // #include <nlohmann/detail/input/binary_reader.hpp>
6046 // __ _____ _____ _____
6047 // __| | __| | | | JSON for Modern C++
6048 // | | |__ | | | | | | version 3.11.2
6049 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
6051 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6052 // SPDX-License-Identifier: MIT
6056 #include <algorithm> // generate_n
6057 #include <array> // array
6058 #include <cmath> // ldexp
6059 #include <cstddef> // size_t
6060 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6061 #include <cstdio> // snprintf
6062 #include <cstring> // memcpy
6063 #include <iterator> // back_inserter
6064 #include <limits> // numeric_limits
6065 #include <string> // char_traits, string
6066 #include <utility> // make_pair, move
6067 #include <vector> // vector
6069 // #include <nlohmann/detail/exceptions.hpp>
6071 // #include <nlohmann/detail/input/input_adapters.hpp>
6072 // __ _____ _____ _____
6073 // __| | __| | | | JSON for Modern C++
6074 // | | |__ | | | | | | version 3.11.2
6075 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
6077 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6078 // SPDX-License-Identifier: MIT
6082 #include <array> // array
6083 #include <cstddef> // size_t
6084 #include <cstring> // strlen
6085 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6086 #include <memory> // shared_ptr, make_shared, addressof
6087 #include <numeric> // accumulate
6088 #include <string> // string, char_traits
6089 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6090 #include <utility> // pair, declval
6093 #include <cstdio> // FILE *
6094 #include <istream> // istream
6095 #endif // JSON_NO_IO
6097 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
6099 // #include <nlohmann/detail/macro_scope.hpp>
6102 NLOHMANN_JSON_NAMESPACE_BEGIN
6106 /// the supported input formats
6107 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6109 ////////////////////
6110 // input adapters //
6111 ////////////////////
6115 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
6116 buffer. This adapter is a very low level adapter.
6118 class file_input_adapter
6121 using char_type = char;
6123 JSON_HEDLEY_NON_NULL(2)
6124 explicit file_input_adapter(std::FILE* f) noexcept
6127 JSON_ASSERT(m_file != nullptr);
6130 // make class move-only
6131 file_input_adapter(const file_input_adapter&) = delete;
6132 file_input_adapter(file_input_adapter&&) noexcept = default;
6133 file_input_adapter& operator=(const file_input_adapter&) = delete;
6134 file_input_adapter& operator=(file_input_adapter&&) = delete;
6135 ~file_input_adapter() = default;
6137 std::char_traits<char>::int_type get_character() noexcept
6139 return std::fgetc(m_file);
6143 /// the file pointer to read from
6149 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
6150 beginning of input. Does not support changing the underlying std::streambuf
6151 in mid-input. Maintains underlying std::istream and std::streambuf to support
6152 subsequent use of standard std::istream operations to process any input
6153 characters following those used in parsing the JSON input. Clears the
6154 std::istream flags; any input errors (e.g., EOF) will be detected by the first
6155 subsequent call for input from the std::istream.
6157 class input_stream_adapter
6160 using char_type = char;
6162 ~input_stream_adapter()
6164 // clear stream flags; we use underlying streambuf I/O, do not
6165 // maintain ifstream flags, except eof
6168 is->clear(is->rdstate() & std::ios::eofbit);
6172 explicit input_stream_adapter(std::istream& i)
6173 : is(&i), sb(i.rdbuf())
6176 // delete because of pointer members
6177 input_stream_adapter(const input_stream_adapter&) = delete;
6178 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6179 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6181 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6182 : is(rhs.is), sb(rhs.sb)
6188 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6189 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6190 // end up as the same value, e.g. 0xFFFFFFFF.
6191 std::char_traits<char>::int_type get_character()
6193 auto res = sb->sbumpc();
6194 // set eof manually, as we don't use the istream interface.
6195 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6197 is->clear(is->rdstate() | std::ios::eofbit);
6203 /// the associated input stream
6204 std::istream* is = nullptr;
6205 std::streambuf* sb = nullptr;
6207 #endif // JSON_NO_IO
6209 // General-purpose iterator-based adapter. It might not be as fast as
6210 // theoretically possible for some containers, but it is extremely versatile.
6211 template<typename IteratorType>
6212 class iterator_input_adapter
6215 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6217 iterator_input_adapter(IteratorType first, IteratorType last)
6218 : current(std::move(first)), end(std::move(last))
6221 typename std::char_traits<char_type>::int_type get_character()
6223 if (JSON_HEDLEY_LIKELY(current != end))
6225 auto result = std::char_traits<char_type>::to_int_type(*current);
6226 std::advance(current, 1);
6230 return std::char_traits<char_type>::eof();
6234 IteratorType current;
6237 template<typename BaseInputAdapter, size_t T>
6238 friend struct wide_string_input_helper;
6242 return current == end;
6247 template<typename BaseInputAdapter, size_t T>
6248 struct wide_string_input_helper;
6250 template<typename BaseInputAdapter>
6251 struct wide_string_input_helper<BaseInputAdapter, 4>
6254 static void fill_buffer(BaseInputAdapter& input,
6255 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6256 size_t& utf8_bytes_index,
6257 size_t& utf8_bytes_filled)
6259 utf8_bytes_index = 0;
6261 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6263 utf8_bytes[0] = std::char_traits<char>::eof();
6264 utf8_bytes_filled = 1;
6268 // get the current character
6269 const auto wc = input.get_character();
6271 // UTF-32 to UTF-8 encoding
6274 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6275 utf8_bytes_filled = 1;
6277 else if (wc <= 0x7FF)
6279 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6280 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6281 utf8_bytes_filled = 2;
6283 else if (wc <= 0xFFFF)
6285 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6286 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6287 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6288 utf8_bytes_filled = 3;
6290 else if (wc <= 0x10FFFF)
6292 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6293 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6294 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6295 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6296 utf8_bytes_filled = 4;
6300 // unknown character
6301 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6302 utf8_bytes_filled = 1;
6308 template<typename BaseInputAdapter>
6309 struct wide_string_input_helper<BaseInputAdapter, 2>
6312 static void fill_buffer(BaseInputAdapter& input,
6313 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6314 size_t& utf8_bytes_index,
6315 size_t& utf8_bytes_filled)
6317 utf8_bytes_index = 0;
6319 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6321 utf8_bytes[0] = std::char_traits<char>::eof();
6322 utf8_bytes_filled = 1;
6326 // get the current character
6327 const auto wc = input.get_character();
6329 // UTF-16 to UTF-8 encoding
6332 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6333 utf8_bytes_filled = 1;
6335 else if (wc <= 0x7FF)
6337 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6338 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6339 utf8_bytes_filled = 2;
6341 else if (0xD800 > wc || wc >= 0xE000)
6343 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6344 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6345 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6346 utf8_bytes_filled = 3;
6350 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6352 const auto wc2 = static_cast<unsigned int>(input.get_character());
6353 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6354 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6355 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6356 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6357 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6358 utf8_bytes_filled = 4;
6362 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6363 utf8_bytes_filled = 1;
6370 // Wraps another input apdater to convert wide character types into individual bytes.
6371 template<typename BaseInputAdapter, typename WideCharType>
6372 class wide_string_input_adapter
6375 using char_type = char;
6377 wide_string_input_adapter(BaseInputAdapter base)
6378 : base_adapter(base) {}
6380 typename std::char_traits<char>::int_type get_character() noexcept
6382 // check if buffer needs to be filled
6383 if (utf8_bytes_index == utf8_bytes_filled)
6385 fill_buffer<sizeof(WideCharType)>();
6387 JSON_ASSERT(utf8_bytes_filled > 0);
6388 JSON_ASSERT(utf8_bytes_index == 0);
6392 JSON_ASSERT(utf8_bytes_filled > 0);
6393 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6394 return utf8_bytes[utf8_bytes_index++];
6398 BaseInputAdapter base_adapter;
6403 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6406 /// a buffer for UTF-8 bytes
6407 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6409 /// index to the utf8_codes array for the next valid byte
6410 std::size_t utf8_bytes_index = 0;
6411 /// number of valid bytes in the utf8_codes array
6412 std::size_t utf8_bytes_filled = 0;
6416 template<typename IteratorType, typename Enable = void>
6417 struct iterator_input_adapter_factory
6419 using iterator_type = IteratorType;
6420 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6421 using adapter_type = iterator_input_adapter<iterator_type>;
6423 static adapter_type create(IteratorType first, IteratorType last)
6425 return adapter_type(std::move(first), std::move(last));
6429 template<typename T>
6430 struct is_iterator_of_multibyte
6432 using value_type = typename std::iterator_traits<T>::value_type;
6435 value = sizeof(value_type) > 1
6439 template<typename IteratorType>
6440 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6442 using iterator_type = IteratorType;
6443 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6444 using base_adapter_type = iterator_input_adapter<iterator_type>;
6445 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6447 static adapter_type create(IteratorType first, IteratorType last)
6449 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6453 // General purpose iterator-based input
6454 template<typename IteratorType>
6455 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6457 using factory_type = iterator_input_adapter_factory<IteratorType>;
6458 return factory_type::create(first, last);
6461 // Convenience shorthand from container to iterator
6462 // Enables ADL on begin(container) and end(container)
6463 // Encloses the using declarations in namespace for not to leak them to outside scope
6465 namespace container_input_adapter_factory_impl
6471 template<typename ContainerType, typename Enable = void>
6472 struct container_input_adapter_factory {};
6474 template<typename ContainerType>
6475 struct container_input_adapter_factory< ContainerType,
6476 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6478 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6480 static adapter_type create(const ContainerType& container)
6482 return input_adapter(begin(container), end(container));
6486 } // namespace container_input_adapter_factory_impl
6488 template<typename ContainerType>
6489 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6491 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6495 // Special cases with fast paths
6496 inline file_input_adapter input_adapter(std::FILE* file)
6498 return file_input_adapter(file);
6501 inline input_stream_adapter input_adapter(std::istream& stream)
6503 return input_stream_adapter(stream);
6506 inline input_stream_adapter input_adapter(std::istream&& stream)
6508 return input_stream_adapter(stream);
6510 #endif // JSON_NO_IO
6512 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6514 // Null-delimited strings, and the like.
6515 template < typename CharT,
6516 typename std::enable_if <
6517 std::is_pointer<CharT>::value&&
6518 !std::is_array<CharT>::value&&
6519 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6520 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6522 contiguous_bytes_input_adapter input_adapter(CharT b)
6524 auto length = std::strlen(reinterpret_cast<const char*>(b));
6525 const auto* ptr = reinterpret_cast<const char*>(b);
6526 return input_adapter(ptr, ptr + length);
6529 template<typename T, std::size_t N>
6530 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6532 return input_adapter(array, array + N);
6535 // This class only handles inputs of input_buffer_adapter type.
6536 // It's required so that expressions like {ptr, len} can be implicitly cast
6537 // to the correct adapter.
6538 class span_input_adapter
6541 template < typename CharT,
6542 typename std::enable_if <
6543 std::is_pointer<CharT>::value&&
6544 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6545 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6547 span_input_adapter(CharT b, std::size_t l)
6548 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6550 template<class IteratorType,
6551 typename std::enable_if<
6552 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6554 span_input_adapter(IteratorType first, IteratorType last)
6555 : ia(input_adapter(first, last)) {}
6557 contiguous_bytes_input_adapter&& get()
6559 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6563 contiguous_bytes_input_adapter ia;
6566 } // namespace detail
6567 NLOHMANN_JSON_NAMESPACE_END
6569 // #include <nlohmann/detail/input/json_sax.hpp>
6570 // __ _____ _____ _____
6571 // __| | __| | | | JSON for Modern C++
6572 // | | |__ | | | | | | version 3.11.2
6573 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
6575 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
6576 // SPDX-License-Identifier: MIT
6581 #include <string> // string
6582 #include <utility> // move
6583 #include <vector> // vector
6585 // #include <nlohmann/detail/exceptions.hpp>
6587 // #include <nlohmann/detail/macro_scope.hpp>
6589 // #include <nlohmann/detail/string_concat.hpp>
6592 NLOHMANN_JSON_NAMESPACE_BEGIN
6595 @brief SAX interface
6597 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
6598 Each function is called in different situations while the input is parsed. The
6599 boolean return value informs the parser whether to continue processing the
6602 template<typename BasicJsonType>
6605 using number_integer_t = typename BasicJsonType::number_integer_t;
6606 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6607 using number_float_t = typename BasicJsonType::number_float_t;
6608 using string_t = typename BasicJsonType::string_t;
6609 using binary_t = typename BasicJsonType::binary_t;
6612 @brief a null value was read
6613 @return whether parsing should proceed
6615 virtual bool null() = 0;
6618 @brief a boolean value was read
6619 @param[in] val boolean value
6620 @return whether parsing should proceed
6622 virtual bool boolean(bool val) = 0;
6625 @brief an integer number was read
6626 @param[in] val integer value
6627 @return whether parsing should proceed
6629 virtual bool number_integer(number_integer_t val) = 0;
6632 @brief an unsigned integer number was read
6633 @param[in] val unsigned integer value
6634 @return whether parsing should proceed
6636 virtual bool number_unsigned(number_unsigned_t val) = 0;
6639 @brief a floating-point number was read
6640 @param[in] val floating-point value
6641 @param[in] s raw token value
6642 @return whether parsing should proceed
6644 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6647 @brief a string value was read
6648 @param[in] val string value
6649 @return whether parsing should proceed
6650 @note It is safe to move the passed string value.
6652 virtual bool string(string_t& val) = 0;
6655 @brief a binary value was read
6656 @param[in] val binary value
6657 @return whether parsing should proceed
6658 @note It is safe to move the passed binary value.
6660 virtual bool binary(binary_t& val) = 0;
6663 @brief the beginning of an object was read
6664 @param[in] elements number of object elements or -1 if unknown
6665 @return whether parsing should proceed
6666 @note binary formats may report the number of elements
6668 virtual bool start_object(std::size_t elements) = 0;
6671 @brief an object key was read
6672 @param[in] val object key
6673 @return whether parsing should proceed
6674 @note It is safe to move the passed string.
6676 virtual bool key(string_t& val) = 0;
6679 @brief the end of an object was read
6680 @return whether parsing should proceed
6682 virtual bool end_object() = 0;
6685 @brief the beginning of an array was read
6686 @param[in] elements number of array elements or -1 if unknown
6687 @return whether parsing should proceed
6688 @note binary formats may report the number of elements
6690 virtual bool start_array(std::size_t elements) = 0;
6693 @brief the end of an array was read
6694 @return whether parsing should proceed
6696 virtual bool end_array() = 0;
6699 @brief a parse error occurred
6700 @param[in] position the position in the input where the error occurs
6701 @param[in] last_token the last read token
6702 @param[in] ex an exception object describing the error
6703 @return whether parsing should proceed (must return false)
6705 virtual bool parse_error(std::size_t position,
6706 const std::string& last_token,
6707 const detail::exception& ex) = 0;
6709 json_sax() = default;
6710 json_sax(const json_sax&) = default;
6711 json_sax(json_sax&&) noexcept = default;
6712 json_sax& operator=(const json_sax&) = default;
6713 json_sax& operator=(json_sax&&) noexcept = default;
6714 virtual ~json_sax() = default;
6721 @brief SAX implementation to create a JSON value from SAX events
6723 This class implements the @ref json_sax interface and processes the SAX events
6724 to create a JSON value which makes it basically a DOM parser. The structure or
6725 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
6726 a pointer to the respective array or object for each recursion depth.
6728 After successful parsing, the value that is passed by reference to the
6729 constructor contains the parsed value.
6731 @tparam BasicJsonType the JSON type
6733 template<typename BasicJsonType>
6734 class json_sax_dom_parser
6737 using number_integer_t = typename BasicJsonType::number_integer_t;
6738 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6739 using number_float_t = typename BasicJsonType::number_float_t;
6740 using string_t = typename BasicJsonType::string_t;
6741 using binary_t = typename BasicJsonType::binary_t;
6744 @param[in,out] r reference to a JSON value that is manipulated while
6746 @param[in] allow_exceptions_ whether parse errors yield exceptions
6748 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6749 : root(r), allow_exceptions(allow_exceptions_)
6752 // make class move-only
6753 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
6754 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6755 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6756 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6757 ~json_sax_dom_parser() = default;
6761 handle_value(nullptr);
6765 bool boolean(bool val)
6771 bool number_integer(number_integer_t val)
6777 bool number_unsigned(number_unsigned_t val)
6783 bool number_float(number_float_t val, const string_t& /*unused*/)
6789 bool string(string_t& val)
6795 bool binary(binary_t& val)
6797 handle_value(std::move(val));
6801 bool start_object(std::size_t len)
6803 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6805 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6807 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6813 bool key(string_t& val)
6815 JSON_ASSERT(!ref_stack.empty());
6816 JSON_ASSERT(ref_stack.back()->is_object());
6818 // add null at given key and store the reference for later
6819 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6825 JSON_ASSERT(!ref_stack.empty());
6826 JSON_ASSERT(ref_stack.back()->is_object());
6828 ref_stack.back()->set_parents();
6829 ref_stack.pop_back();
6833 bool start_array(std::size_t len)
6835 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6837 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6839 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6847 JSON_ASSERT(!ref_stack.empty());
6848 JSON_ASSERT(ref_stack.back()->is_array());
6850 ref_stack.back()->set_parents();
6851 ref_stack.pop_back();
6855 template<class Exception>
6856 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6857 const Exception& ex)
6860 static_cast<void>(ex);
6861 if (allow_exceptions)
6868 constexpr bool is_errored() const
6875 @invariant If the ref stack is empty, then the passed value will be the new
6877 @invariant If the ref stack contains a value, then it is an array or an
6878 object to which we can add elements
6880 template<typename Value>
6881 JSON_HEDLEY_RETURNS_NON_NULL
6882 BasicJsonType* handle_value(Value&& v)
6884 if (ref_stack.empty())
6886 root = BasicJsonType(std::forward<Value>(v));
6890 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6892 if (ref_stack.back()->is_array())
6894 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6895 return &(ref_stack.back()->m_data.m_value.array->back());
6898 JSON_ASSERT(ref_stack.back()->is_object());
6899 JSON_ASSERT(object_element);
6900 *object_element = BasicJsonType(std::forward<Value>(v));
6901 return object_element;
6904 /// the parsed JSON value
6905 BasicJsonType& root;
6906 /// stack to model hierarchy of values
6907 std::vector<BasicJsonType*> ref_stack {};
6908 /// helper to hold the reference for the next object element
6909 BasicJsonType* object_element = nullptr;
6910 /// whether a syntax error occurred
6911 bool errored = false;
6912 /// whether to throw exceptions in case of errors
6913 const bool allow_exceptions = true;
6916 template<typename BasicJsonType>
6917 class json_sax_dom_callback_parser
6920 using number_integer_t = typename BasicJsonType::number_integer_t;
6921 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6922 using number_float_t = typename BasicJsonType::number_float_t;
6923 using string_t = typename BasicJsonType::string_t;
6924 using binary_t = typename BasicJsonType::binary_t;
6925 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6926 using parse_event_t = typename BasicJsonType::parse_event_t;
6928 json_sax_dom_callback_parser(BasicJsonType& r,
6929 const parser_callback_t cb,
6930 const bool allow_exceptions_ = true)
6931 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6933 keep_stack.push_back(true);
6936 // make class move-only
6937 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
6938 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6939 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
6940 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6941 ~json_sax_dom_callback_parser() = default;
6945 handle_value(nullptr);
6949 bool boolean(bool val)
6955 bool number_integer(number_integer_t val)
6961 bool number_unsigned(number_unsigned_t val)
6967 bool number_float(number_float_t val, const string_t& /*unused*/)
6973 bool string(string_t& val)
6979 bool binary(binary_t& val)
6981 handle_value(std::move(val));
6985 bool start_object(std::size_t len)
6987 // check callback for object start
6988 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
6989 keep_stack.push_back(keep);
6991 auto val = handle_value(BasicJsonType::value_t::object, true);
6992 ref_stack.push_back(val.second);
6994 // check object limit
6995 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6997 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7003 bool key(string_t& val)
7005 BasicJsonType k = BasicJsonType(val);
7007 // check callback for key
7008 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7009 key_keep_stack.push_back(keep);
7011 // add discarded value at given key and store the reference for later
7012 if (keep && ref_stack.back())
7014 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7022 if (ref_stack.back())
7024 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7027 *ref_stack.back() = discarded;
7031 ref_stack.back()->set_parents();
7035 JSON_ASSERT(!ref_stack.empty());
7036 JSON_ASSERT(!keep_stack.empty());
7037 ref_stack.pop_back();
7038 keep_stack.pop_back();
7040 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7042 // remove discarded value
7043 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7045 if (it->is_discarded())
7047 ref_stack.back()->erase(it);
7056 bool start_array(std::size_t len)
7058 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7059 keep_stack.push_back(keep);
7061 auto val = handle_value(BasicJsonType::value_t::array, true);
7062 ref_stack.push_back(val.second);
7064 // check array limit
7065 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7067 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7077 if (ref_stack.back())
7079 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7082 ref_stack.back()->set_parents();
7087 *ref_stack.back() = discarded;
7091 JSON_ASSERT(!ref_stack.empty());
7092 JSON_ASSERT(!keep_stack.empty());
7093 ref_stack.pop_back();
7094 keep_stack.pop_back();
7096 // remove discarded value
7097 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7099 ref_stack.back()->m_data.m_value.array->pop_back();
7105 template<class Exception>
7106 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7107 const Exception& ex)
7110 static_cast<void>(ex);
7111 if (allow_exceptions)
7118 constexpr bool is_errored() const
7125 @param[in] v value to add to the JSON value we build during parsing
7126 @param[in] skip_callback whether we should skip calling the callback
7127 function; this is required after start_array() and
7128 start_object() SAX events, because otherwise we would call the
7129 callback function with an empty array or object, respectively.
7131 @invariant If the ref stack is empty, then the passed value will be the new
7133 @invariant If the ref stack contains a value, then it is an array or an
7134 object to which we can add elements
7136 @return pair of boolean (whether value should be kept) and pointer (to the
7137 passed value in the ref_stack hierarchy; nullptr if not kept)
7139 template<typename Value>
7140 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7142 JSON_ASSERT(!keep_stack.empty());
7144 // do not handle this value if we know it would be added to a discarded
7146 if (!keep_stack.back())
7148 return {false, nullptr};
7152 auto value = BasicJsonType(std::forward<Value>(v));
7155 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7157 // do not handle this value if we just learnt it shall be discarded
7160 return {false, nullptr};
7163 if (ref_stack.empty())
7165 root = std::move(value);
7166 return {true, &root};
7169 // skip this value if we already decided to skip the parent
7170 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7171 if (!ref_stack.back())
7173 return {false, nullptr};
7176 // we now only expect arrays and objects
7177 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7180 if (ref_stack.back()->is_array())
7182 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7183 return {true, &(ref_stack.back()->m_data.m_value.array->back())};
7187 JSON_ASSERT(ref_stack.back()->is_object());
7188 // check if we should store an element for the current key
7189 JSON_ASSERT(!key_keep_stack.empty());
7190 const bool store_element = key_keep_stack.back();
7191 key_keep_stack.pop_back();
7195 return {false, nullptr};
7198 JSON_ASSERT(object_element);
7199 *object_element = std::move(value);
7200 return {true, object_element};
7203 /// the parsed JSON value
7204 BasicJsonType& root;
7205 /// stack to model hierarchy of values
7206 std::vector<BasicJsonType*> ref_stack {};
7207 /// stack to manage which values to keep
7208 std::vector<bool> keep_stack {};
7209 /// stack to manage which object keys to keep
7210 std::vector<bool> key_keep_stack {};
7211 /// helper to hold the reference for the next object element
7212 BasicJsonType* object_element = nullptr;
7213 /// whether a syntax error occurred
7214 bool errored = false;
7215 /// callback function
7216 const parser_callback_t callback = nullptr;
7217 /// whether to throw exceptions in case of errors
7218 const bool allow_exceptions = true;
7219 /// a discarded value for the callback
7220 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7223 template<typename BasicJsonType>
7224 class json_sax_acceptor
7227 using number_integer_t = typename BasicJsonType::number_integer_t;
7228 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7229 using number_float_t = typename BasicJsonType::number_float_t;
7230 using string_t = typename BasicJsonType::string_t;
7231 using binary_t = typename BasicJsonType::binary_t;
7238 bool boolean(bool /*unused*/)
7243 bool number_integer(number_integer_t /*unused*/)
7248 bool number_unsigned(number_unsigned_t /*unused*/)
7253 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7258 bool string(string_t& /*unused*/)
7263 bool binary(binary_t& /*unused*/)
7268 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7273 bool key(string_t& /*unused*/)
7283 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7293 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7299 } // namespace detail
7300 NLOHMANN_JSON_NAMESPACE_END
7302 // #include <nlohmann/detail/input/lexer.hpp>
7303 // __ _____ _____ _____
7304 // __| | __| | | | JSON for Modern C++
7305 // | | |__ | | | | | | version 3.11.2
7306 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
7308 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7309 // SPDX-License-Identifier: MIT
7313 #include <array> // array
7314 #include <clocale> // localeconv
7315 #include <cstddef> // size_t
7316 #include <cstdio> // snprintf
7317 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7318 #include <initializer_list> // initializer_list
7319 #include <string> // char_traits, string
7320 #include <utility> // move
7321 #include <vector> // vector
7323 // #include <nlohmann/detail/input/input_adapters.hpp>
7325 // #include <nlohmann/detail/input/position_t.hpp>
7327 // #include <nlohmann/detail/macro_scope.hpp>
7330 NLOHMANN_JSON_NAMESPACE_BEGIN
7338 template<typename BasicJsonType>
7342 /// token types for the parser
7343 enum class token_type
7345 uninitialized, ///< indicating the scanner is uninitialized
7346 literal_true, ///< the `true` literal
7347 literal_false, ///< the `false` literal
7348 literal_null, ///< the `null` literal
7349 value_string, ///< a string -- use get_string() for actual value
7350 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7351 value_integer, ///< a signed integer -- use get_number_integer() for actual value
7352 value_float, ///< an floating point number -- use get_number_float() for actual value
7353 begin_array, ///< the character for array begin `[`
7354 begin_object, ///< the character for object begin `{`
7355 end_array, ///< the character for array end `]`
7356 end_object, ///< the character for object end `}`
7357 name_separator, ///< the name separator `:`
7358 value_separator, ///< the value separator `,`
7359 parse_error, ///< indicating a parse error
7360 end_of_input, ///< indicating the end of the input buffer
7361 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7364 /// return name of values of type token_type (only used for errors)
7365 JSON_HEDLEY_RETURNS_NON_NULL
7367 static const char* token_type_name(const token_type t) noexcept
7371 case token_type::uninitialized:
7372 return "<uninitialized>";
7373 case token_type::literal_true:
7374 return "true literal";
7375 case token_type::literal_false:
7376 return "false literal";
7377 case token_type::literal_null:
7378 return "null literal";
7379 case token_type::value_string:
7380 return "string literal";
7381 case token_type::value_unsigned:
7382 case token_type::value_integer:
7383 case token_type::value_float:
7384 return "number literal";
7385 case token_type::begin_array:
7387 case token_type::begin_object:
7389 case token_type::end_array:
7391 case token_type::end_object:
7393 case token_type::name_separator:
7395 case token_type::value_separator:
7397 case token_type::parse_error:
7398 return "<parse error>";
7399 case token_type::end_of_input:
7400 return "end of input";
7401 case token_type::literal_or_value:
7402 return "'[', '{', or a literal";
7404 default: // catch non-enum values
7405 return "unknown token";
7411 @brief lexical analysis
7413 This class organizes the lexical analysis during JSON deserialization.
7415 template<typename BasicJsonType, typename InputAdapterType>
7416 class lexer : public lexer_base<BasicJsonType>
7418 using number_integer_t = typename BasicJsonType::number_integer_t;
7419 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7420 using number_float_t = typename BasicJsonType::number_float_t;
7421 using string_t = typename BasicJsonType::string_t;
7422 using char_type = typename InputAdapterType::char_type;
7423 using char_int_type = typename std::char_traits<char_type>::int_type;
7426 using token_type = typename lexer_base<BasicJsonType>::token_type;
7428 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7429 : ia(std::move(adapter))
7430 , ignore_comments(ignore_comments_)
7431 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7434 // delete because of pointer members
7435 lexer(const lexer&) = delete;
7436 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7437 lexer& operator=(lexer&) = delete;
7438 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7442 /////////////////////
7444 /////////////////////
7446 /// return the locale-dependent decimal point
7448 static char get_decimal_point() noexcept
7450 const auto* loc = localeconv();
7451 JSON_ASSERT(loc != nullptr);
7452 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7455 /////////////////////
7457 /////////////////////
7460 @brief get codepoint from 4 hex characters following `\u`
7462 For input "\u c1 c2 c3 c4" the codepoint is:
7463 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7464 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7466 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7467 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7468 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7469 between the ASCII value of the character and the desired integer value.
7471 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7476 // this function only makes sense after reading `\u`
7477 JSON_ASSERT(current == 'u');
7480 const auto factors = { 12u, 8u, 4u, 0u };
7481 for (const auto factor : factors)
7485 if (current >= '0' && current <= '9')
7487 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7489 else if (current >= 'A' && current <= 'F')
7491 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7493 else if (current >= 'a' && current <= 'f')
7495 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7503 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7508 @brief check if the next byte(s) are inside a given range
7510 Adds the current byte and, for each passed range, reads a new byte and
7511 checks if it is inside the range. If a violation was detected, set up an
7512 error message and return false. Otherwise, return true.
7514 @param[in] ranges list of integers; interpreted as list of pairs of
7515 inclusive lower and upper bound, respectively
7517 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7518 1, 2, or 3 pairs. This precondition is enforced by an assertion.
7520 @return true if and only if no range violation was detected
7522 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7524 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7527 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7530 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7536 error_message = "invalid string: ill-formed UTF-8 byte";
7545 @brief scan a string literal
7547 This function scans a string according to Sect. 7 of RFC 8259. While
7548 scanning, bytes are escaped and copied into buffer token_buffer. Then the
7549 function returns successfully, token_buffer is *not* null-terminated (as it
7550 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7553 @return token_type::value_string if string could be successfully scanned,
7554 token_type::parse_error otherwise
7556 @note In case of errors, variable error_message contains a textual
7559 token_type scan_string()
7561 // reset token_buffer (ignore opening quote)
7564 // we entered the function by reading an open quote
7565 JSON_ASSERT(current == '\"');
7569 // get next character
7572 // end of file while parsing string
7573 case std::char_traits<char_type>::eof():
7575 error_message = "invalid string: missing closing quote";
7576 return token_type::parse_error;
7582 return token_type::value_string;
7626 const int codepoint1 = get_codepoint();
7627 int codepoint = codepoint1; // start with codepoint1
7629 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7631 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7632 return token_type::parse_error;
7635 // check if code point is a high surrogate
7636 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7638 // expect next \uxxxx entry
7639 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7641 const int codepoint2 = get_codepoint();
7643 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7645 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7646 return token_type::parse_error;
7649 // check if codepoint2 is a low surrogate
7650 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7652 // overwrite codepoint
7653 codepoint = static_cast<int>(
7654 // high surrogate occupies the most significant 22 bits
7655 (static_cast<unsigned int>(codepoint1) << 10u)
7656 // low surrogate occupies the least significant 15 bits
7657 + static_cast<unsigned int>(codepoint2)
7658 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7659 // in the result, so we have to subtract with:
7660 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7665 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7666 return token_type::parse_error;
7671 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7672 return token_type::parse_error;
7677 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7679 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7680 return token_type::parse_error;
7684 // result of the above calculation yields a proper codepoint
7685 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7687 // translate codepoint into bytes
7688 if (codepoint < 0x80)
7690 // 1-byte characters: 0xxxxxxx (ASCII)
7691 add(static_cast<char_int_type>(codepoint));
7693 else if (codepoint <= 0x7FF)
7695 // 2-byte characters: 110xxxxx 10xxxxxx
7696 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7697 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7699 else if (codepoint <= 0xFFFF)
7701 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7702 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7703 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7704 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7708 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7709 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7710 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7711 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7712 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7718 // other characters after escape
7720 error_message = "invalid string: forbidden character after backslash";
7721 return token_type::parse_error;
7727 // invalid control characters
7730 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7731 return token_type::parse_error;
7736 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7737 return token_type::parse_error;
7742 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7743 return token_type::parse_error;
7748 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7749 return token_type::parse_error;
7754 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7755 return token_type::parse_error;
7760 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7761 return token_type::parse_error;
7766 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7767 return token_type::parse_error;
7772 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7773 return token_type::parse_error;
7778 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7779 return token_type::parse_error;
7784 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7785 return token_type::parse_error;
7790 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7791 return token_type::parse_error;
7796 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7797 return token_type::parse_error;
7802 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7803 return token_type::parse_error;
7808 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7809 return token_type::parse_error;
7814 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7815 return token_type::parse_error;
7820 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7821 return token_type::parse_error;
7826 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7827 return token_type::parse_error;
7832 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7833 return token_type::parse_error;
7838 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7839 return token_type::parse_error;
7844 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7845 return token_type::parse_error;
7850 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7851 return token_type::parse_error;
7856 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7857 return token_type::parse_error;
7862 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7863 return token_type::parse_error;
7868 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7869 return token_type::parse_error;
7874 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7875 return token_type::parse_error;
7880 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7881 return token_type::parse_error;
7886 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7887 return token_type::parse_error;
7892 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7893 return token_type::parse_error;
7898 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7899 return token_type::parse_error;
7904 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7905 return token_type::parse_error;
7910 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7911 return token_type::parse_error;
7916 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7917 return token_type::parse_error;
7920 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8020 // U+0080..U+07FF: bytes C2..DF 80..BF
8052 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8054 return token_type::parse_error;
8059 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8062 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8064 return token_type::parse_error;
8069 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8070 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8086 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8088 return token_type::parse_error;
8093 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8096 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8098 return token_type::parse_error;
8103 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8106 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8108 return token_type::parse_error;
8113 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8118 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8120 return token_type::parse_error;
8125 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8128 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8130 return token_type::parse_error;
8135 // remaining bytes (80..C1 and F5..FF) are ill-formed
8138 error_message = "invalid string: ill-formed UTF-8 byte";
8139 return token_type::parse_error;
8146 * @brief scan a comment
8147 * @return whether comment could be scanned successfully
8153 // single-line comments skip input until a newline or EOF is read
8162 case std::char_traits<char_type>::eof():
8172 // multi-line comments skip input until */ is read
8179 case std::char_traits<char_type>::eof():
8182 error_message = "invalid comment; missing closing '*/'";
8207 // unexpected character after reading '/'
8210 error_message = "invalid comment; expecting '/' or '*' after '/'";
8216 JSON_HEDLEY_NON_NULL(2)
8217 static void strtof(float& f, const char* str, char** endptr) noexcept
8219 f = std::strtof(str, endptr);
8222 JSON_HEDLEY_NON_NULL(2)
8223 static void strtof(double& f, const char* str, char** endptr) noexcept
8225 f = std::strtod(str, endptr);
8228 JSON_HEDLEY_NON_NULL(2)
8229 static void strtof(long double& f, const char* str, char** endptr) noexcept
8231 f = std::strtold(str, endptr);
8235 @brief scan a number literal
8237 This function scans a string according to Sect. 6 of RFC 8259.
8239 The function is realized with a deterministic finite state machine derived
8240 from the grammar described in RFC 8259. Starting in state "init", the
8241 input is read and used to determined the next state. Only state "done"
8242 accepts the number. State "error" is a trap state to model errors. In the
8243 table below, "anything" means any character but the ones listed before.
8245 state | 0 | 1-9 | e E | + | - | . | anything
8246 ---------|----------|----------|----------|---------|---------|----------|-----------
8247 init | zero | any1 | [error] | [error] | minus | [error] | [error]
8248 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
8249 zero | done | done | exponent | done | done | decimal1 | done
8250 any1 | any1 | any1 | exponent | done | done | decimal1 | done
8251 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
8252 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
8253 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
8254 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
8255 any2 | any2 | any2 | done | done | done | done | done
8257 The state machine is realized with one label per state (prefixed with
8258 "scan_number_") and `goto` statements between them. The state machine
8259 contains cycles, but any cycle can be left when EOF is read. Therefore,
8260 the function is guaranteed to terminate.
8262 During scanning, the read bytes are stored in token_buffer. This string is
8263 then converted to a signed integer, an unsigned integer, or a
8264 floating-point number.
8266 @return token_type::value_unsigned, token_type::value_integer, or
8267 token_type::value_float if number could be successfully scanned,
8268 token_type::parse_error otherwise
8270 @note The scanner is independent of the current locale. Internally, the
8271 locale's decimal point is used instead of `.` to work with the
8272 locale-dependent converters.
8274 token_type scan_number() // lgtm [cpp/use-of-goto]
8276 // reset token_buffer to store the number's bytes
8279 // the type of the parsed number; initially set to unsigned; will be
8280 // changed if minus sign, decimal point or exponent is read
8281 token_type number_type = token_type::value_unsigned;
8283 // state (init): we just found out we need to scan a number
8289 goto scan_number_minus;
8295 goto scan_number_zero;
8309 goto scan_number_any1;
8312 // all other characters are rejected outside scan_number()
8313 default: // LCOV_EXCL_LINE
8314 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8318 // state: we just parsed a leading minus sign
8319 number_type = token_type::value_integer;
8325 goto scan_number_zero;
8339 goto scan_number_any1;
8344 error_message = "invalid number; expected digit after '-'";
8345 return token_type::parse_error;
8350 // state: we just parse a zero (maybe with a leading minus sign)
8355 add(decimal_point_char);
8356 goto scan_number_decimal1;
8363 goto scan_number_exponent;
8367 goto scan_number_done;
8371 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8386 goto scan_number_any1;
8391 add(decimal_point_char);
8392 goto scan_number_decimal1;
8399 goto scan_number_exponent;
8403 goto scan_number_done;
8406 scan_number_decimal1:
8407 // state: we just parsed a decimal point
8408 number_type = token_type::value_float;
8423 goto scan_number_decimal2;
8428 error_message = "invalid number; expected digit after '.'";
8429 return token_type::parse_error;
8433 scan_number_decimal2:
8434 // we just parsed at least one number after a decimal point
8449 goto scan_number_decimal2;
8456 goto scan_number_exponent;
8460 goto scan_number_done;
8463 scan_number_exponent:
8464 // we just parsed an exponent
8465 number_type = token_type::value_float;
8472 goto scan_number_sign;
8487 goto scan_number_any2;
8493 "invalid number; expected '+', '-', or digit after exponent";
8494 return token_type::parse_error;
8499 // we just parsed an exponent sign
8514 goto scan_number_any2;
8519 error_message = "invalid number; expected digit after exponent sign";
8520 return token_type::parse_error;
8525 // we just parsed a number after the exponent or exponent sign
8540 goto scan_number_any2;
8544 goto scan_number_done;
8548 // unget the character after the number (we only read it to know that
8549 // we are done scanning a number)
8552 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8555 // try to parse integers first and fall back to floats
8556 if (number_type == token_type::value_unsigned)
8558 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8560 // we checked the number format before
8561 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8565 value_unsigned = static_cast<number_unsigned_t>(x);
8566 if (value_unsigned == x)
8568 return token_type::value_unsigned;
8572 else if (number_type == token_type::value_integer)
8574 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8576 // we checked the number format before
8577 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8581 value_integer = static_cast<number_integer_t>(x);
8582 if (value_integer == x)
8584 return token_type::value_integer;
8589 // this code is reached if we parse a floating-point number or if an
8590 // integer conversion above failed
8591 strtof(value_float, token_buffer.data(), &endptr);
8593 // we checked the number format before
8594 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8596 return token_type::value_float;
8600 @param[in] literal_text the literal text to expect
8601 @param[in] length the length of the passed literal text
8602 @param[in] return_type the token type to return on success
8604 JSON_HEDLEY_NON_NULL(2)
8605 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8606 token_type return_type)
8608 JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
8609 for (std::size_t i = 1; i < length; ++i)
8611 if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8613 error_message = "invalid literal";
8614 return token_type::parse_error;
8620 /////////////////////
8622 /////////////////////
8624 /// reset token_buffer; current character is beginning of token
8625 void reset() noexcept
8627 token_buffer.clear();
8628 token_string.clear();
8629 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8633 @brief get next character from the input
8635 This function provides the interface to the used input adapter. It does
8636 not throw in case the input reached EOF, but returns a
8637 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
8638 for use in error messages.
8640 @return character read from the input
8644 ++position.chars_read_total;
8645 ++position.chars_read_current_line;
8649 // just reset the next_unget variable and work with current
8654 current = ia.get_character();
8657 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8659 token_string.push_back(std::char_traits<char_type>::to_char_type(current));
8662 if (current == '\n')
8664 ++position.lines_read;
8665 position.chars_read_current_line = 0;
8672 @brief unget current character (read it again on next get)
8674 We implement unget by setting variable next_unget to true. The input is not
8675 changed - we just simulate ungetting by modifying chars_read_total,
8676 chars_read_current_line, and token_string. The next call to get() will
8677 behave as if the unget character is read again.
8683 --position.chars_read_total;
8685 // in case we "unget" a newline, we have to also decrement the lines_read
8686 if (position.chars_read_current_line == 0)
8688 if (position.lines_read > 0)
8690 --position.lines_read;
8695 --position.chars_read_current_line;
8698 if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
8700 JSON_ASSERT(!token_string.empty());
8701 token_string.pop_back();
8705 /// add a character to token_buffer
8706 void add(char_int_type c)
8708 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8712 /////////////////////
8714 /////////////////////
8716 /// return integer value
8717 constexpr number_integer_t get_number_integer() const noexcept
8719 return value_integer;
8722 /// return unsigned integer value
8723 constexpr number_unsigned_t get_number_unsigned() const noexcept
8725 return value_unsigned;
8728 /// return floating-point value
8729 constexpr number_float_t get_number_float() const noexcept
8734 /// return current string value (implicitly resets the token; useful only once)
8735 string_t& get_string()
8737 return token_buffer;
8740 /////////////////////
8742 /////////////////////
8744 /// return position of last read token
8745 constexpr position_t get_position() const noexcept
8750 /// return the last read token (for errors only). Will never contain EOF
8751 /// (an arbitrary value that is not a valid char value, often -1), because
8752 /// 255 may legitimately occur. May contain NUL, which should be escaped.
8753 std::string get_token_string() const
8755 // escape control characters
8757 for (const auto c : token_string)
8759 if (static_cast<unsigned char>(c) <= '\x1F')
8761 // escape control characters
8762 std::array<char, 9> cs{{}};
8763 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8764 result += cs.data();
8768 // add character as is
8769 result.push_back(static_cast<std::string::value_type>(c));
8776 /// return syntax error message
8777 JSON_HEDLEY_RETURNS_NON_NULL
8778 constexpr const char* get_error_message() const noexcept
8780 return error_message;
8783 /////////////////////
8785 /////////////////////
8788 @brief skip the UTF-8 byte order mark
8789 @return true iff there is no BOM or the correct BOM has been skipped
8795 // check if we completely parse the BOM
8796 return get() == 0xBB && get() == 0xBF;
8799 // the first character is not the beginning of the BOM; unget it to
8805 void skip_whitespace()
8811 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8816 // initially, skip the BOM
8817 if (position.chars_read_total == 0 && !skip_bom())
8819 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8820 return token_type::parse_error;
8823 // read next character and ignore whitespace
8827 while (ignore_comments && current == '/')
8829 if (!scan_comment())
8831 return token_type::parse_error;
8834 // skip following whitespace
8840 // structural characters
8842 return token_type::begin_array;
8844 return token_type::end_array;
8846 return token_type::begin_object;
8848 return token_type::end_object;
8850 return token_type::name_separator;
8852 return token_type::value_separator;
8857 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8858 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8862 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8863 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8867 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8868 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8873 return scan_string();
8887 return scan_number();
8889 // end of input (the null byte is needed when parsing from
8892 case std::char_traits<char_type>::eof():
8893 return token_type::end_of_input;
8897 error_message = "invalid literal";
8898 return token_type::parse_error;
8904 InputAdapterType ia;
8906 /// whether comments should be ignored (true) or signaled as errors (false)
8907 const bool ignore_comments = false;
8909 /// the current character
8910 char_int_type current = std::char_traits<char_type>::eof();
8912 /// whether the next get() call should just return current
8913 bool next_unget = false;
8915 /// the start position of the current token
8916 position_t position {};
8918 /// raw input token string (for error messages)
8919 std::vector<char_type> token_string {};
8921 /// buffer for variable-length tokens (numbers, strings)
8922 string_t token_buffer {};
8924 /// a description of occurred lexer errors
8925 const char* error_message = "";
8928 number_integer_t value_integer = 0;
8929 number_unsigned_t value_unsigned = 0;
8930 number_float_t value_float = 0;
8932 /// the decimal point
8933 const char_int_type decimal_point_char = '.';
8936 } // namespace detail
8937 NLOHMANN_JSON_NAMESPACE_END
8939 // #include <nlohmann/detail/macro_scope.hpp>
8941 // #include <nlohmann/detail/meta/is_sax.hpp>
8942 // __ _____ _____ _____
8943 // __| | __| | | | JSON for Modern C++
8944 // | | |__ | | | | | | version 3.11.2
8945 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
8947 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8948 // SPDX-License-Identifier: MIT
8952 #include <cstdint> // size_t
8953 #include <utility> // declval
8954 #include <string> // string
8956 // #include <nlohmann/detail/abi_macros.hpp>
8958 // #include <nlohmann/detail/meta/detected.hpp>
8960 // #include <nlohmann/detail/meta/type_traits.hpp>
8963 NLOHMANN_JSON_NAMESPACE_BEGIN
8967 template<typename T>
8968 using null_function_t = decltype(std::declval<T&>().null());
8970 template<typename T>
8971 using boolean_function_t =
8972 decltype(std::declval<T&>().boolean(std::declval<bool>()));
8974 template<typename T, typename Integer>
8975 using number_integer_function_t =
8976 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
8978 template<typename T, typename Unsigned>
8979 using number_unsigned_function_t =
8980 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
8982 template<typename T, typename Float, typename String>
8983 using number_float_function_t = decltype(std::declval<T&>().number_float(
8984 std::declval<Float>(), std::declval<const String&>()));
8986 template<typename T, typename String>
8987 using string_function_t =
8988 decltype(std::declval<T&>().string(std::declval<String&>()));
8990 template<typename T, typename Binary>
8991 using binary_function_t =
8992 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
8994 template<typename T>
8995 using start_object_function_t =
8996 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
8998 template<typename T, typename String>
8999 using key_function_t =
9000 decltype(std::declval<T&>().key(std::declval<String&>()));
9002 template<typename T>
9003 using end_object_function_t = decltype(std::declval<T&>().end_object());
9005 template<typename T>
9006 using start_array_function_t =
9007 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9009 template<typename T>
9010 using end_array_function_t = decltype(std::declval<T&>().end_array());
9012 template<typename T, typename Exception>
9013 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9014 std::declval<std::size_t>(), std::declval<const std::string&>(),
9015 std::declval<const Exception&>()));
9017 template<typename SAX, typename BasicJsonType>
9021 static_assert(is_basic_json<BasicJsonType>::value,
9022 "BasicJsonType must be of type basic_json<...>");
9024 using number_integer_t = typename BasicJsonType::number_integer_t;
9025 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9026 using number_float_t = typename BasicJsonType::number_float_t;
9027 using string_t = typename BasicJsonType::string_t;
9028 using binary_t = typename BasicJsonType::binary_t;
9029 using exception_t = typename BasicJsonType::exception;
9032 static constexpr bool value =
9033 is_detected_exact<bool, null_function_t, SAX>::value &&
9034 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9035 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9036 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9037 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9038 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9039 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9040 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9041 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9042 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9043 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9044 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9045 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9048 template<typename SAX, typename BasicJsonType>
9049 struct is_sax_static_asserts
9052 static_assert(is_basic_json<BasicJsonType>::value,
9053 "BasicJsonType must be of type basic_json<...>");
9055 using number_integer_t = typename BasicJsonType::number_integer_t;
9056 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9057 using number_float_t = typename BasicJsonType::number_float_t;
9058 using string_t = typename BasicJsonType::string_t;
9059 using binary_t = typename BasicJsonType::binary_t;
9060 using exception_t = typename BasicJsonType::exception;
9063 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9064 "Missing/invalid function: bool null()");
9065 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9066 "Missing/invalid function: bool boolean(bool)");
9067 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9068 "Missing/invalid function: bool boolean(bool)");
9070 is_detected_exact<bool, number_integer_function_t, SAX,
9071 number_integer_t>::value,
9072 "Missing/invalid function: bool number_integer(number_integer_t)");
9074 is_detected_exact<bool, number_unsigned_function_t, SAX,
9075 number_unsigned_t>::value,
9076 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9077 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9078 number_float_t, string_t>::value,
9079 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9081 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9082 "Missing/invalid function: bool string(string_t&)");
9084 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9085 "Missing/invalid function: bool binary(binary_t&)");
9086 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9087 "Missing/invalid function: bool start_object(std::size_t)");
9088 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9089 "Missing/invalid function: bool key(string_t&)");
9090 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9091 "Missing/invalid function: bool end_object()");
9092 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9093 "Missing/invalid function: bool start_array(std::size_t)");
9094 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9095 "Missing/invalid function: bool end_array()");
9097 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9098 "Missing/invalid function: bool parse_error(std::size_t, const "
9099 "std::string&, const exception&)");
9102 } // namespace detail
9103 NLOHMANN_JSON_NAMESPACE_END
9105 // #include <nlohmann/detail/meta/type_traits.hpp>
9107 // #include <nlohmann/detail/string_concat.hpp>
9109 // #include <nlohmann/detail/value_t.hpp>
9112 NLOHMANN_JSON_NAMESPACE_BEGIN
9116 /// how to treat CBOR tags
9117 enum class cbor_tag_handler_t
9119 error, ///< throw a parse_error exception in case of a tag
9120 ignore, ///< ignore tags
9121 store ///< store tags as binary type
9125 @brief determine system byte order
9127 @return true if and only if system's byte order is little endian
9129 @note from https://stackoverflow.com/a/1001328/266378
9131 static inline bool little_endianness(int num = 1) noexcept
9133 return *reinterpret_cast<char*>(&num) == 1;
9142 @brief deserialization of CBOR, MessagePack, and UBJSON values
9144 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9147 using number_integer_t = typename BasicJsonType::number_integer_t;
9148 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9149 using number_float_t = typename BasicJsonType::number_float_t;
9150 using string_t = typename BasicJsonType::string_t;
9151 using binary_t = typename BasicJsonType::binary_t;
9152 using json_sax_t = SAX;
9153 using char_type = typename InputAdapterType::char_type;
9154 using char_int_type = typename std::char_traits<char_type>::int_type;
9158 @brief create a binary reader
9160 @param[in] adapter input adapter to read from
9162 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9164 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9167 // make class move-only
9168 binary_reader(const binary_reader&) = delete;
9169 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9170 binary_reader& operator=(const binary_reader&) = delete;
9171 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9172 ~binary_reader() = default;
9175 @param[in] format the binary format to parse
9176 @param[in] sax_ a SAX event processor
9177 @param[in] strict whether to expect the input to be consumed completed
9178 @param[in] tag_handler how to treat CBOR tags
9180 @return whether parsing was successful
9182 JSON_HEDLEY_NON_NULL(3)
9183 bool sax_parse(const input_format_t format,
9185 const bool strict = true,
9186 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9189 bool result = false;
9193 case input_format_t::bson:
9194 result = parse_bson_internal();
9197 case input_format_t::cbor:
9198 result = parse_cbor_internal(true, tag_handler);
9201 case input_format_t::msgpack:
9202 result = parse_msgpack_internal();
9205 case input_format_t::ubjson:
9206 case input_format_t::bjdata:
9207 result = parse_ubjson_internal();
9210 case input_format_t::json: // LCOV_EXCL_LINE
9211 default: // LCOV_EXCL_LINE
9212 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9215 // strict mode: next byte must be EOF
9216 if (result && strict)
9218 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9227 if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
9229 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9230 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9243 @brief Reads in a BSON-object and passes it to the SAX-parser.
9244 @return whether a valid BSON-value was passed to the SAX parser
9246 bool parse_bson_internal()
9248 std::int32_t document_size{};
9249 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9251 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9256 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9261 return sax->end_object();
9265 @brief Parses a C-style string from the BSON input.
9266 @param[in,out] result A reference to the string variable where the read
9267 string is to be stored.
9268 @return `true` if the \x00-byte indicating the end of the string was
9269 encountered before the EOF; false` indicates an unexpected EOF.
9271 bool get_bson_cstr(string_t& result)
9273 auto out = std::back_inserter(result);
9277 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9281 if (current == 0x00)
9285 *out++ = static_cast<typename string_t::value_type>(current);
9290 @brief Parses a zero-terminated string of length @a len from the BSON
9292 @param[in] len The length (including the zero-byte at the end) of the
9294 @param[in,out] result A reference to the string variable where the read
9295 string is to be stored.
9296 @tparam NumberType The type of the length @a len
9298 @return `true` if the string was successfully parsed
9300 template<typename NumberType>
9301 bool get_bson_string(const NumberType len, string_t& result)
9303 if (JSON_HEDLEY_UNLIKELY(len < 1))
9305 auto last_token = get_token_string();
9306 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9307 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9310 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
9314 @brief Parses a byte array input of length @a len from the BSON input.
9315 @param[in] len The length of the byte array to be read.
9316 @param[in,out] result A reference to the binary variable where the read
9317 array is to be stored.
9318 @tparam NumberType The type of the length @a len
9320 @return `true` if the byte array was successfully parsed
9322 template<typename NumberType>
9323 bool get_bson_binary(const NumberType len, binary_t& result)
9325 if (JSON_HEDLEY_UNLIKELY(len < 0))
9327 auto last_token = get_token_string();
9328 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9329 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9332 // All BSON binary values have a subtype
9333 std::uint8_t subtype{};
9334 get_number<std::uint8_t>(input_format_t::bson, subtype);
9335 result.set_subtype(subtype);
9337 return get_binary(input_format_t::bson, len, result);
9341 @brief Read a BSON document element of the given @a element_type.
9342 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
9343 @param[in] element_type_parse_position The position in the input stream,
9344 where the `element_type` was read.
9345 @warning Not all BSON element types are supported yet. An unsupported
9346 @a element_type will give rise to a parse_error.114:
9347 Unsupported BSON record type 0x...
9348 @return whether a valid BSON-object/array was passed to the SAX parser
9350 bool parse_bson_element_internal(const char_int_type element_type,
9351 const std::size_t element_type_parse_position)
9353 switch (element_type)
9355 case 0x01: // double
9358 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9361 case 0x02: // string
9365 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9368 case 0x03: // object
9370 return parse_bson_internal();
9375 return parse_bson_array();
9378 case 0x05: // binary
9382 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9385 case 0x08: // boolean
9387 return sax->boolean(get() != 0);
9397 std::int32_t value{};
9398 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9403 std::int64_t value{};
9404 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9407 default: // anything else not supported (yet)
9409 std::array<char, 3> cr{{}};
9410 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9411 const std::string cr_str{cr.data()};
9412 return sax->parse_error(element_type_parse_position, cr_str,
9413 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9419 @brief Read a BSON element list (as specified in the BSON-spec)
9421 The same binary layout is used for objects and arrays, hence it must be
9422 indicated with the argument @a is_array which one is expected
9423 (true --> array, false --> object).
9425 @param[in] is_array Determines if the element list being read is to be
9426 treated as an object (@a is_array == false), or as an
9427 array (@a is_array == true).
9428 @return whether a valid BSON-object/array was passed to the SAX parser
9430 bool parse_bson_element_list(const bool is_array)
9434 while (auto element_type = get())
9436 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9441 const std::size_t element_type_parse_position = chars_read;
9442 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9447 if (!is_array && !sax->key(key))
9452 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9457 // get_bson_cstr only appends
9465 @brief Reads an array from the BSON input and passes it to the SAX-parser.
9466 @return whether a valid BSON-array was passed to the SAX parser
9468 bool parse_bson_array()
9470 std::int32_t document_size{};
9471 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9473 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9478 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9483 return sax->end_array();
9491 @param[in] get_char whether a new character should be retrieved from the
9492 input (true) or whether the last read character should
9493 be considered instead (false)
9494 @param[in] tag_handler how CBOR tags should be treated
9496 @return whether a valid CBOR value was passed to the SAX parser
9498 bool parse_cbor_internal(const bool get_char,
9499 const cbor_tag_handler_t tag_handler)
9501 switch (get_char ? get() : current)
9504 case std::char_traits<char_type>::eof():
9505 return unexpect_eof(input_format_t::cbor, "value");
9507 // Integer 0x00..0x17 (0..23)
9532 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9534 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9536 std::uint8_t number{};
9537 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9540 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9542 std::uint16_t number{};
9543 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9546 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9548 std::uint32_t number{};
9549 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9552 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9554 std::uint64_t number{};
9555 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9558 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9583 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9585 case 0x38: // Negative integer (one-byte uint8_t follows)
9587 std::uint8_t number{};
9588 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9591 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9593 std::uint16_t number{};
9594 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9597 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9599 std::uint32_t number{};
9600 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9603 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9605 std::uint64_t number{};
9606 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9607 - static_cast<number_integer_t>(number));
9610 // Binary data (0x00..0x17 bytes follow)
9635 case 0x58: // Binary data (one-byte uint8_t for n follows)
9636 case 0x59: // Binary data (two-byte uint16_t for n follow)
9637 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9638 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9639 case 0x5F: // Binary data (indefinite length)
9642 return get_cbor_binary(b) && sax->binary(b);
9645 // UTF-8 string (0x00..0x17 bytes follow)
9670 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9671 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9672 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9673 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9674 case 0x7F: // UTF-8 string (indefinite length)
9677 return get_cbor_string(s) && sax->string(s);
9680 // array (0x00..0x17 data items follow)
9705 return get_cbor_array(
9706 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9708 case 0x98: // array (one-byte uint8_t for n follows)
9711 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9714 case 0x99: // array (two-byte uint16_t for n follow)
9716 std::uint16_t len{};
9717 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9720 case 0x9A: // array (four-byte uint32_t for n follow)
9722 std::uint32_t len{};
9723 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9726 case 0x9B: // array (eight-byte uint64_t for n follow)
9728 std::uint64_t len{};
9729 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9732 case 0x9F: // array (indefinite length)
9733 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9735 // map (0x00..0x17 pairs of data items follow)
9760 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9762 case 0xB8: // map (one-byte uint8_t for n follows)
9765 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9768 case 0xB9: // map (two-byte uint16_t for n follow)
9770 std::uint16_t len{};
9771 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9774 case 0xBA: // map (four-byte uint32_t for n follow)
9776 std::uint32_t len{};
9777 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9780 case 0xBB: // map (eight-byte uint64_t for n follow)
9782 std::uint64_t len{};
9783 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9786 case 0xBF: // map (indefinite length)
9787 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9789 case 0xC6: // tagged item
9804 case 0xD8: // tagged item (1 bytes follow)
9805 case 0xD9: // tagged item (2 bytes follow)
9806 case 0xDA: // tagged item (4 bytes follow)
9807 case 0xDB: // tagged item (8 bytes follow)
9809 switch (tag_handler)
9811 case cbor_tag_handler_t::error:
9813 auto last_token = get_token_string();
9814 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9815 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9818 case cbor_tag_handler_t::ignore:
9820 // ignore binary subtype
9825 std::uint8_t subtype_to_ignore{};
9826 get_number(input_format_t::cbor, subtype_to_ignore);
9831 std::uint16_t subtype_to_ignore{};
9832 get_number(input_format_t::cbor, subtype_to_ignore);
9837 std::uint32_t subtype_to_ignore{};
9838 get_number(input_format_t::cbor, subtype_to_ignore);
9843 std::uint64_t subtype_to_ignore{};
9844 get_number(input_format_t::cbor, subtype_to_ignore);
9850 return parse_cbor_internal(true, tag_handler);
9853 case cbor_tag_handler_t::store:
9856 // use binary subtype and store in binary container
9861 std::uint8_t subtype{};
9862 get_number(input_format_t::cbor, subtype);
9863 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9868 std::uint16_t subtype{};
9869 get_number(input_format_t::cbor, subtype);
9870 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9875 std::uint32_t subtype{};
9876 get_number(input_format_t::cbor, subtype);
9877 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9882 std::uint64_t subtype{};
9883 get_number(input_format_t::cbor, subtype);
9884 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9888 return parse_cbor_internal(true, tag_handler);
9891 return get_cbor_binary(b) && sax->binary(b);
9894 default: // LCOV_EXCL_LINE
9895 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9896 return false; // LCOV_EXCL_LINE
9901 return sax->boolean(false);
9904 return sax->boolean(true);
9909 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9911 const auto byte1_raw = get();
9912 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9916 const auto byte2_raw = get();
9917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9922 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9923 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9925 // code from RFC 7049, Appendix D, Figure 3:
9926 // As half-precision floating-point numbers were only added
9927 // to IEEE 754 in 2008, today's programming platforms often
9928 // still only have limited support for them. It is very
9929 // easy to include at least decoding support for them even
9930 // without such support. An example of a small decoder for
9931 // half-precision floating-point numbers in the C language
9932 // is shown in Fig. 3.
9933 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
9934 const double val = [&half]
9936 const int exp = (half >> 10u) & 0x1Fu;
9937 const unsigned int mant = half & 0x3FFu;
9938 JSON_ASSERT(0 <= exp&& exp <= 32);
9939 JSON_ASSERT(mant <= 1024);
9943 return std::ldexp(mant, -24);
9946 ? std::numeric_limits<double>::infinity()
9947 : std::numeric_limits<double>::quiet_NaN();
9949 return std::ldexp(mant + 1024, exp - 25);
9952 return sax->number_float((half & 0x8000u) != 0
9953 ? static_cast<number_float_t>(-val)
9954 : static_cast<number_float_t>(val), "");
9957 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
9960 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9963 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
9966 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
9969 default: // anything else (0xFF is handled inside the other types)
9971 auto last_token = get_token_string();
9972 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9973 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9979 @brief reads a CBOR string
9981 This function first reads starting bytes to determine the expected
9982 string length and then copies this number of bytes into a string.
9983 Additionally, CBOR's strings with indefinite lengths are supported.
9985 @param[out] result created string
9987 @return whether string creation completed
9989 bool get_cbor_string(string_t& result)
9991 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
9998 // UTF-8 string (0x00..0x17 bytes follow)
10024 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10027 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10029 std::uint8_t len{};
10030 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10033 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10035 std::uint16_t len{};
10036 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10039 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10041 std::uint32_t len{};
10042 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10045 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10047 std::uint64_t len{};
10048 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10051 case 0x7F: // UTF-8 string (indefinite length)
10053 while (get() != 0xFF)
10056 if (!get_cbor_string(chunk))
10060 result.append(chunk);
10067 auto last_token = get_token_string();
10068 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10069 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10075 @brief reads a CBOR byte array
10077 This function first reads starting bytes to determine the expected
10078 byte array length and then copies this number of bytes into the byte array.
10079 Additionally, CBOR's byte arrays with indefinite lengths are supported.
10081 @param[out] result created byte array
10083 @return whether byte array creation completed
10085 bool get_cbor_binary(binary_t& result)
10087 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10094 // Binary data (0x00..0x17 bytes follow)
10120 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10123 case 0x58: // Binary data (one-byte uint8_t for n follows)
10125 std::uint8_t len{};
10126 return get_number(input_format_t::cbor, len) &&
10127 get_binary(input_format_t::cbor, len, result);
10130 case 0x59: // Binary data (two-byte uint16_t for n follow)
10132 std::uint16_t len{};
10133 return get_number(input_format_t::cbor, len) &&
10134 get_binary(input_format_t::cbor, len, result);
10137 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10139 std::uint32_t len{};
10140 return get_number(input_format_t::cbor, len) &&
10141 get_binary(input_format_t::cbor, len, result);
10144 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10146 std::uint64_t len{};
10147 return get_number(input_format_t::cbor, len) &&
10148 get_binary(input_format_t::cbor, len, result);
10151 case 0x5F: // Binary data (indefinite length)
10153 while (get() != 0xFF)
10156 if (!get_cbor_binary(chunk))
10160 result.insert(result.end(), chunk.begin(), chunk.end());
10167 auto last_token = get_token_string();
10168 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10169 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10175 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an
10176 array of indefinite size
10177 @param[in] tag_handler how CBOR tags should be treated
10178 @return whether array creation completed
10180 bool get_cbor_array(const std::size_t len,
10181 const cbor_tag_handler_t tag_handler)
10183 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10188 if (len != static_cast<std::size_t>(-1))
10190 for (std::size_t i = 0; i < len; ++i)
10192 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10200 while (get() != 0xFF)
10202 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10209 return sax->end_array();
10213 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an
10214 object of indefinite size
10215 @param[in] tag_handler how CBOR tags should be treated
10216 @return whether object creation completed
10218 bool get_cbor_object(const std::size_t len,
10219 const cbor_tag_handler_t tag_handler)
10221 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10229 if (len != static_cast<std::size_t>(-1))
10231 for (std::size_t i = 0; i < len; ++i)
10234 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10239 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10248 while (get() != 0xFF)
10250 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10255 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10264 return sax->end_object();
10272 @return whether a valid MessagePack value was passed to the SAX parser
10274 bool parse_msgpack_internal()
10279 case std::char_traits<char_type>::eof():
10280 return unexpect_eof(input_format_t::msgpack, "value");
10411 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10430 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10449 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10484 case 0xD9: // str 8
10485 case 0xDA: // str 16
10486 case 0xDB: // str 32
10489 return get_msgpack_string(s) && sax->string(s);
10493 return sax->null();
10495 case 0xC2: // false
10496 return sax->boolean(false);
10499 return sax->boolean(true);
10501 case 0xC4: // bin 8
10502 case 0xC5: // bin 16
10503 case 0xC6: // bin 32
10504 case 0xC7: // ext 8
10505 case 0xC8: // ext 16
10506 case 0xC9: // ext 32
10507 case 0xD4: // fixext 1
10508 case 0xD5: // fixext 2
10509 case 0xD6: // fixext 4
10510 case 0xD7: // fixext 8
10511 case 0xD8: // fixext 16
10514 return get_msgpack_binary(b) && sax->binary(b);
10517 case 0xCA: // float 32
10520 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10523 case 0xCB: // float 64
10526 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10529 case 0xCC: // uint 8
10531 std::uint8_t number{};
10532 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10535 case 0xCD: // uint 16
10537 std::uint16_t number{};
10538 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10541 case 0xCE: // uint 32
10543 std::uint32_t number{};
10544 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10547 case 0xCF: // uint 64
10549 std::uint64_t number{};
10550 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10553 case 0xD0: // int 8
10555 std::int8_t number{};
10556 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10559 case 0xD1: // int 16
10561 std::int16_t number{};
10562 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10565 case 0xD2: // int 32
10567 std::int32_t number{};
10568 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10571 case 0xD3: // int 64
10573 std::int64_t number{};
10574 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10577 case 0xDC: // array 16
10579 std::uint16_t len{};
10580 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10583 case 0xDD: // array 32
10585 std::uint32_t len{};
10586 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10589 case 0xDE: // map 16
10591 std::uint16_t len{};
10592 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10595 case 0xDF: // map 32
10597 std::uint32_t len{};
10598 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10634 return sax->number_integer(static_cast<std::int8_t>(current));
10636 default: // anything else
10638 auto last_token = get_token_string();
10639 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10640 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10646 @brief reads a MessagePack string
10648 This function first reads starting bytes to determine the expected
10649 string length and then copies this number of bytes into a string.
10651 @param[out] result created string
10653 @return whether string creation completed
10655 bool get_msgpack_string(string_t& result)
10657 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10698 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10701 case 0xD9: // str 8
10703 std::uint8_t len{};
10704 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10707 case 0xDA: // str 16
10709 std::uint16_t len{};
10710 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10713 case 0xDB: // str 32
10715 std::uint32_t len{};
10716 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10721 auto last_token = get_token_string();
10722 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10723 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10729 @brief reads a MessagePack byte array
10731 This function first reads starting bytes to determine the expected
10732 byte array length and then copies this number of bytes into a byte array.
10734 @param[out] result created byte array
10736 @return whether byte array creation completed
10738 bool get_msgpack_binary(binary_t& result)
10740 // helper function to set the subtype
10741 auto assign_and_return_true = [&result](std::int8_t subtype)
10743 result.set_subtype(static_cast<std::uint8_t>(subtype));
10749 case 0xC4: // bin 8
10751 std::uint8_t len{};
10752 return get_number(input_format_t::msgpack, len) &&
10753 get_binary(input_format_t::msgpack, len, result);
10756 case 0xC5: // bin 16
10758 std::uint16_t len{};
10759 return get_number(input_format_t::msgpack, len) &&
10760 get_binary(input_format_t::msgpack, len, result);
10763 case 0xC6: // bin 32
10765 std::uint32_t len{};
10766 return get_number(input_format_t::msgpack, len) &&
10767 get_binary(input_format_t::msgpack, len, result);
10770 case 0xC7: // ext 8
10772 std::uint8_t len{};
10773 std::int8_t subtype{};
10774 return get_number(input_format_t::msgpack, len) &&
10775 get_number(input_format_t::msgpack, subtype) &&
10776 get_binary(input_format_t::msgpack, len, result) &&
10777 assign_and_return_true(subtype);
10780 case 0xC8: // ext 16
10782 std::uint16_t len{};
10783 std::int8_t subtype{};
10784 return get_number(input_format_t::msgpack, len) &&
10785 get_number(input_format_t::msgpack, subtype) &&
10786 get_binary(input_format_t::msgpack, len, result) &&
10787 assign_and_return_true(subtype);
10790 case 0xC9: // ext 32
10792 std::uint32_t len{};
10793 std::int8_t subtype{};
10794 return get_number(input_format_t::msgpack, len) &&
10795 get_number(input_format_t::msgpack, subtype) &&
10796 get_binary(input_format_t::msgpack, len, result) &&
10797 assign_and_return_true(subtype);
10800 case 0xD4: // fixext 1
10802 std::int8_t subtype{};
10803 return get_number(input_format_t::msgpack, subtype) &&
10804 get_binary(input_format_t::msgpack, 1, result) &&
10805 assign_and_return_true(subtype);
10808 case 0xD5: // fixext 2
10810 std::int8_t subtype{};
10811 return get_number(input_format_t::msgpack, subtype) &&
10812 get_binary(input_format_t::msgpack, 2, result) &&
10813 assign_and_return_true(subtype);
10816 case 0xD6: // fixext 4
10818 std::int8_t subtype{};
10819 return get_number(input_format_t::msgpack, subtype) &&
10820 get_binary(input_format_t::msgpack, 4, result) &&
10821 assign_and_return_true(subtype);
10824 case 0xD7: // fixext 8
10826 std::int8_t subtype{};
10827 return get_number(input_format_t::msgpack, subtype) &&
10828 get_binary(input_format_t::msgpack, 8, result) &&
10829 assign_and_return_true(subtype);
10832 case 0xD8: // fixext 16
10834 std::int8_t subtype{};
10835 return get_number(input_format_t::msgpack, subtype) &&
10836 get_binary(input_format_t::msgpack, 16, result) &&
10837 assign_and_return_true(subtype);
10840 default: // LCOV_EXCL_LINE
10841 return false; // LCOV_EXCL_LINE
10846 @param[in] len the length of the array
10847 @return whether array creation completed
10849 bool get_msgpack_array(const std::size_t len)
10851 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10856 for (std::size_t i = 0; i < len; ++i)
10858 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10864 return sax->end_array();
10868 @param[in] len the length of the object
10869 @return whether object creation completed
10871 bool get_msgpack_object(const std::size_t len)
10873 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10879 for (std::size_t i = 0; i < len; ++i)
10882 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10887 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10894 return sax->end_object();
10902 @param[in] get_char whether a new character should be retrieved from the
10903 input (true, default) or whether the last read
10904 character should be considered instead
10906 @return whether a valid UBJSON value was passed to the SAX parser
10908 bool parse_ubjson_internal(const bool get_char = true)
10910 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10914 @brief reads a UBJSON string
10916 This function is either called after reading the 'S' byte explicitly
10917 indicating a string, or in case of an object key where the 'S' byte can be
10920 @param[out] result created string
10921 @param[in] get_char whether a new character should be retrieved from the
10922 input (true, default) or whether the last read
10923 character should be considered instead
10925 @return whether string creation completed
10927 bool get_ubjson_string(string_t& result, const bool get_char = true)
10931 get(); // TODO(niels): may we ignore N here?
10934 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
10943 std::uint8_t len{};
10944 return get_number(input_format, len) && get_string(input_format, len, result);
10950 return get_number(input_format, len) && get_string(input_format, len, result);
10955 std::int16_t len{};
10956 return get_number(input_format, len) && get_string(input_format, len, result);
10961 std::int32_t len{};
10962 return get_number(input_format, len) && get_string(input_format, len, result);
10967 std::int64_t len{};
10968 return get_number(input_format, len) && get_string(input_format, len, result);
10973 if (input_format != input_format_t::bjdata)
10977 std::uint16_t len{};
10978 return get_number(input_format, len) && get_string(input_format, len, result);
10983 if (input_format != input_format_t::bjdata)
10987 std::uint32_t len{};
10988 return get_number(input_format, len) && get_string(input_format, len, result);
10993 if (input_format != input_format_t::bjdata)
10997 std::uint64_t len{};
10998 return get_number(input_format, len) && get_string(input_format, len, result);
11004 auto last_token = get_token_string();
11005 std::string message;
11007 if (input_format != input_format_t::bjdata)
11009 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11013 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11015 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11019 @param[out] dim an integer vector storing the ND array dimensions
11020 @return whether reading ND array size vector is successful
11022 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11024 std::pair<std::size_t, char_int_type> size_and_type;
11026 bool no_ndarray = true;
11028 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11033 if (size_and_type.first != npos)
11035 if (size_and_type.second != 0)
11037 if (size_and_type.second != 'N')
11039 for (std::size_t i = 0; i < size_and_type.first; ++i)
11041 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11045 dim.push_back(dimlen);
11051 for (std::size_t i = 0; i < size_and_type.first; ++i)
11053 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11057 dim.push_back(dimlen);
11063 while (current != ']')
11065 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11069 dim.push_back(dimlen);
11077 @param[out] result determined size
11078 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
11079 or ndarray dimension is not allowed; `false` means ndarray
11080 is allowed; for output, `true` means an ndarray is found;
11081 is_ndarray can only return `true` when its initial value
11083 @param[in] prefix type marker if already read, otherwise set to 0
11085 @return whether size determination completed
11087 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11091 prefix = get_ignore_noop();
11098 std::uint8_t number{};
11099 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11103 result = static_cast<std::size_t>(number);
11109 std::int8_t number{};
11110 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11116 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11117 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11119 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11125 std::int16_t number{};
11126 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11132 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11133 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11135 result = static_cast<std::size_t>(number);
11141 std::int32_t number{};
11142 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11148 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11149 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11151 result = static_cast<std::size_t>(number);
11157 std::int64_t number{};
11158 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11164 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11165 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11167 if (!value_in_range_of<std::size_t>(number))
11169 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11170 exception_message(input_format, "integer value overflow", "size"), nullptr));
11172 result = static_cast<std::size_t>(number);
11178 if (input_format != input_format_t::bjdata)
11182 std::uint16_t number{};
11183 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11187 result = static_cast<std::size_t>(number);
11193 if (input_format != input_format_t::bjdata)
11197 std::uint32_t number{};
11198 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11202 result = conditional_static_cast<std::size_t>(number);
11208 if (input_format != input_format_t::bjdata)
11212 std::uint64_t number{};
11213 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11217 if (!value_in_range_of<std::size_t>(number))
11219 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11220 exception_message(input_format, "integer value overflow", "size"), nullptr));
11222 result = detail::conditional_static_cast<std::size_t>(number);
11228 if (input_format != input_format_t::bjdata)
11232 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11234 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11236 std::vector<size_t> dim;
11237 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11241 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11243 result = dim.at(dim.size() - 1);
11246 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11248 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11257 string_t key = "_ArraySize_";
11258 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11266 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11268 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11270 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11276 return sax->end_array();
11285 auto last_token = get_token_string();
11286 std::string message;
11288 if (input_format != input_format_t::bjdata)
11290 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11294 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11296 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11300 @brief determine the type and size for a container
11302 In the optimized UBJSON format, a type and a size can be provided to allow
11303 for a more compact representation.
11305 @param[out] result pair of the size and the type
11306 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
11308 @return whether pair creation completed
11310 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11312 result.first = npos; // size
11313 result.second = 0; // type
11314 bool is_ndarray = false;
11318 if (current == '$')
11320 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11321 if (input_format == input_format_t::bjdata
11322 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11324 auto last_token = get_token_string();
11325 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11326 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11329 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11335 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11337 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11341 auto last_token = get_token_string();
11342 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11343 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11346 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11347 if (input_format == input_format_t::bjdata && is_ndarray)
11349 if (inside_ndarray)
11351 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11352 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11354 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11359 if (current == '#')
11361 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11362 if (input_format == input_format_t::bjdata && is_ndarray)
11364 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11365 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11374 @param prefix the previously read or set type prefix
11375 @return whether value creation completed
11377 bool get_ubjson_value(const char_int_type prefix)
11381 case std::char_traits<char_type>::eof(): // EOF
11382 return unexpect_eof(input_format, "value");
11385 return sax->boolean(true);
11387 return sax->boolean(false);
11390 return sax->null();
11394 std::uint8_t number{};
11395 return get_number(input_format, number) && sax->number_unsigned(number);
11400 std::int8_t number{};
11401 return get_number(input_format, number) && sax->number_integer(number);
11406 std::int16_t number{};
11407 return get_number(input_format, number) && sax->number_integer(number);
11412 std::int32_t number{};
11413 return get_number(input_format, number) && sax->number_integer(number);
11418 std::int64_t number{};
11419 return get_number(input_format, number) && sax->number_integer(number);
11424 if (input_format != input_format_t::bjdata)
11428 std::uint16_t number{};
11429 return get_number(input_format, number) && sax->number_unsigned(number);
11434 if (input_format != input_format_t::bjdata)
11438 std::uint32_t number{};
11439 return get_number(input_format, number) && sax->number_unsigned(number);
11444 if (input_format != input_format_t::bjdata)
11448 std::uint64_t number{};
11449 return get_number(input_format, number) && sax->number_unsigned(number);
11454 if (input_format != input_format_t::bjdata)
11458 const auto byte1_raw = get();
11459 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11463 const auto byte2_raw = get();
11464 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11469 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11470 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11472 // code from RFC 7049, Appendix D, Figure 3:
11473 // As half-precision floating-point numbers were only added
11474 // to IEEE 754 in 2008, today's programming platforms often
11475 // still only have limited support for them. It is very
11476 // easy to include at least decoding support for them even
11477 // without such support. An example of a small decoder for
11478 // half-precision floating-point numbers in the C language
11479 // is shown in Fig. 3.
11480 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11481 const double val = [&half]
11483 const int exp = (half >> 10u) & 0x1Fu;
11484 const unsigned int mant = half & 0x3FFu;
11485 JSON_ASSERT(0 <= exp&& exp <= 32);
11486 JSON_ASSERT(mant <= 1024);
11490 return std::ldexp(mant, -24);
11493 ? std::numeric_limits<double>::infinity()
11494 : std::numeric_limits<double>::quiet_NaN();
11496 return std::ldexp(mant + 1024, exp - 25);
11499 return sax->number_float((half & 0x8000u) != 0
11500 ? static_cast<number_float_t>(-val)
11501 : static_cast<number_float_t>(val), "");
11507 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11513 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11518 return get_ubjson_high_precision_number();
11524 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11528 if (JSON_HEDLEY_UNLIKELY(current > 127))
11530 auto last_token = get_token_string();
11531 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11532 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11534 string_t s(1, static_cast<typename string_t::value_type>(current));
11535 return sax->string(s);
11538 case 'S': // string
11541 return get_ubjson_string(s) && sax->string(s);
11545 return get_ubjson_array();
11547 case '{': // object
11548 return get_ubjson_object();
11550 default: // anything else
11553 auto last_token = get_token_string();
11554 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11558 @return whether array creation completed
11560 bool get_ubjson_array()
11562 std::pair<std::size_t, char_int_type> size_and_type;
11563 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11568 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11569 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11571 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11573 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11574 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11576 return p.first < t;
11578 string_t key = "_ArrayType_";
11579 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11581 auto last_token = get_token_string();
11582 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11583 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11586 string_t type = it->second; // sax->string() takes a reference
11587 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11592 if (size_and_type.second == 'C')
11594 size_and_type.second = 'U';
11597 key = "_ArrayData_";
11598 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11603 for (std::size_t i = 0; i < size_and_type.first; ++i)
11605 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11611 return (sax->end_array() && sax->end_object());
11614 if (size_and_type.first != npos)
11616 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11621 if (size_and_type.second != 0)
11623 if (size_and_type.second != 'N')
11625 for (std::size_t i = 0; i < size_and_type.first; ++i)
11627 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11636 for (std::size_t i = 0; i < size_and_type.first; ++i)
11638 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11647 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11652 while (current != ']')
11654 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11662 return sax->end_array();
11666 @return whether object creation completed
11668 bool get_ubjson_object()
11670 std::pair<std::size_t, char_int_type> size_and_type;
11671 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11676 // do not accept ND-array size in objects in BJData
11677 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11679 auto last_token = get_token_string();
11680 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11681 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11685 if (size_and_type.first != npos)
11687 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11692 if (size_and_type.second != 0)
11694 for (std::size_t i = 0; i < size_and_type.first; ++i)
11696 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11700 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11709 for (std::size_t i = 0; i < size_and_type.first; ++i)
11711 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11715 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11725 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11730 while (current != '}')
11732 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11736 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11745 return sax->end_object();
11748 // Note, no reader for UBJSON binary types is implemented because they do
11751 bool get_ubjson_high_precision_number()
11753 // get size of following number string
11754 std::size_t size{};
11755 bool no_ndarray = true;
11756 auto res = get_ubjson_size_value(size, no_ndarray);
11757 if (JSON_HEDLEY_UNLIKELY(!res))
11762 // get number string
11763 std::vector<char> number_vector;
11764 for (std::size_t i = 0; i < size; ++i)
11767 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11771 number_vector.push_back(static_cast<char>(current));
11774 // parse number string
11775 using ia_type = decltype(detail::input_adapter(number_vector));
11776 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11777 const auto result_number = number_lexer.scan();
11778 const auto number_string = number_lexer.get_token_string();
11779 const auto result_remainder = number_lexer.scan();
11781 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11783 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11785 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11786 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11789 switch (result_number)
11791 case token_type::value_integer:
11792 return sax->number_integer(number_lexer.get_number_integer());
11793 case token_type::value_unsigned:
11794 return sax->number_unsigned(number_lexer.get_number_unsigned());
11795 case token_type::value_float:
11796 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11797 case token_type::uninitialized:
11798 case token_type::literal_true:
11799 case token_type::literal_false:
11800 case token_type::literal_null:
11801 case token_type::value_string:
11802 case token_type::begin_array:
11803 case token_type::begin_object:
11804 case token_type::end_array:
11805 case token_type::end_object:
11806 case token_type::name_separator:
11807 case token_type::value_separator:
11808 case token_type::parse_error:
11809 case token_type::end_of_input:
11810 case token_type::literal_or_value:
11812 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11813 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11817 ///////////////////////
11818 // Utility functions //
11819 ///////////////////////
11822 @brief get next character from the input
11824 This function provides the interface to the used input adapter. It does
11825 not throw in case the input reached EOF, but returns a -'ve valued
11826 `std::char_traits<char_type>::eof()` in that case.
11828 @return character read from the input
11830 char_int_type get()
11833 return current = ia.get_character();
11837 @return character read from the input after ignoring all 'N' entries
11839 char_int_type get_ignore_noop()
11845 while (current == 'N');
11851 @brief read a number from the input
11853 @tparam NumberType the type of the number
11854 @param[in] format the current format (for diagnostics)
11855 @param[out] result number of type @a NumberType
11857 @return whether conversion completed
11859 @note This function needs to respect the system's endianness, because
11860 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11861 (big endian) and therefore need reordering on little endian systems.
11862 On the other hand, BSON and BJData use little endian and should reorder
11863 on big endian systems.
11865 template<typename NumberType, bool InputIsLittleEndian = false>
11866 bool get_number(const input_format_t format, NumberType& result)
11868 // step 1: read input into array with system's byte order
11869 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11870 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11873 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11878 // reverse byte order prior to conversion if necessary
11879 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11881 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11885 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11889 // step 2: convert array into number of type T and return
11890 std::memcpy(&result, vec.data(), sizeof(NumberType));
11895 @brief create a string by reading characters from the input
11897 @tparam NumberType the type of the number
11898 @param[in] format the current format (for diagnostics)
11899 @param[in] len number of characters to read
11900 @param[out] result string created by reading @a len bytes
11902 @return whether string creation completed
11904 @note We can not reserve @a len bytes for the result, because @a len
11905 may be too large. Usually, @ref unexpect_eof() detects the end of
11906 the input before we run out of string memory.
11908 template<typename NumberType>
11909 bool get_string(const input_format_t format,
11910 const NumberType len,
11913 bool success = true;
11914 for (NumberType i = 0; i < len; i++)
11917 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11922 result.push_back(static_cast<typename string_t::value_type>(current));
11928 @brief create a byte array by reading bytes from the input
11930 @tparam NumberType the type of the number
11931 @param[in] format the current format (for diagnostics)
11932 @param[in] len number of bytes to read
11933 @param[out] result byte array created by reading @a len bytes
11935 @return whether byte array creation completed
11937 @note We can not reserve @a len bytes for the result, because @a len
11938 may be too large. Usually, @ref unexpect_eof() detects the end of
11939 the input before we run out of memory.
11941 template<typename NumberType>
11942 bool get_binary(const input_format_t format,
11943 const NumberType len,
11946 bool success = true;
11947 for (NumberType i = 0; i < len; i++)
11950 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
11955 result.push_back(static_cast<std::uint8_t>(current));
11961 @param[in] format the current format (for diagnostics)
11962 @param[in] context further context information (for diagnostics)
11963 @return whether the last read character is not EOF
11965 JSON_HEDLEY_NON_NULL(3)
11966 bool unexpect_eof(const input_format_t format, const char* context) const
11968 if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
11970 return sax->parse_error(chars_read, "<end of file>",
11971 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
11977 @return a string representation of the last read byte
11979 std::string get_token_string() const
11981 std::array<char, 3> cr{{}};
11982 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
11983 return std::string{cr.data()};
11987 @param[in] format the current format
11988 @param[in] detail a detailed error message
11989 @param[in] context further context information
11990 @return a message string to use in the parse_error exceptions
11992 std::string exception_message(const input_format_t format,
11993 const std::string& detail,
11994 const std::string& context) const
11996 std::string error_msg = "syntax error while parsing ";
12000 case input_format_t::cbor:
12001 error_msg += "CBOR";
12004 case input_format_t::msgpack:
12005 error_msg += "MessagePack";
12008 case input_format_t::ubjson:
12009 error_msg += "UBJSON";
12012 case input_format_t::bson:
12013 error_msg += "BSON";
12016 case input_format_t::bjdata:
12017 error_msg += "BJData";
12020 case input_format_t::json: // LCOV_EXCL_LINE
12021 default: // LCOV_EXCL_LINE
12022 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12025 return concat(error_msg, ' ', context, ": ", detail);
12029 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12032 InputAdapterType ia;
12034 /// the current character
12035 char_int_type current = std::char_traits<char_type>::eof();
12037 /// the number of characters read
12038 std::size_t chars_read = 0;
12040 /// whether we can assume little endianness
12041 const bool is_little_endian = little_endianness();
12044 const input_format_t input_format = input_format_t::json;
12047 json_sax_t* sax = nullptr;
12049 // excluded markers in bjdata optimized type
12050 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12051 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12053 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12054 make_array<bjd_type>( \
12055 bjd_type{'C', "char"}, \
12056 bjd_type{'D', "double"}, \
12057 bjd_type{'I', "int16"}, \
12058 bjd_type{'L', "int64"}, \
12059 bjd_type{'M', "uint64"}, \
12060 bjd_type{'U', "uint8"}, \
12061 bjd_type{'d', "single"}, \
12062 bjd_type{'i', "int8"}, \
12063 bjd_type{'l', "int32"}, \
12064 bjd_type{'m', "uint32"}, \
12065 bjd_type{'u', "uint16"})
12067 JSON_PRIVATE_UNLESS_TESTED:
12069 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12070 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12071 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12073 using bjd_type = std::pair<char_int_type, string_t>;
12074 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12075 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12076 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12078 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12079 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12082 #ifndef JSON_HAS_CPP_17
12083 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12084 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12087 } // namespace detail
12088 NLOHMANN_JSON_NAMESPACE_END
12090 // #include <nlohmann/detail/input/input_adapters.hpp>
12092 // #include <nlohmann/detail/input/lexer.hpp>
12094 // #include <nlohmann/detail/input/parser.hpp>
12095 // __ _____ _____ _____
12096 // __| | __| | | | JSON for Modern C++
12097 // | | |__ | | | | | | version 3.11.2
12098 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
12100 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12101 // SPDX-License-Identifier: MIT
12105 #include <cmath> // isfinite
12106 #include <cstdint> // uint8_t
12107 #include <functional> // function
12108 #include <string> // string
12109 #include <utility> // move
12110 #include <vector> // vector
12112 // #include <nlohmann/detail/exceptions.hpp>
12114 // #include <nlohmann/detail/input/input_adapters.hpp>
12116 // #include <nlohmann/detail/input/json_sax.hpp>
12118 // #include <nlohmann/detail/input/lexer.hpp>
12120 // #include <nlohmann/detail/macro_scope.hpp>
12122 // #include <nlohmann/detail/meta/is_sax.hpp>
12124 // #include <nlohmann/detail/string_concat.hpp>
12126 // #include <nlohmann/detail/value_t.hpp>
12129 NLOHMANN_JSON_NAMESPACE_BEGIN
12136 enum class parse_event_t : std::uint8_t
12138 /// the parser read `{` and started to process a JSON object
12140 /// the parser read `}` and finished processing a JSON object
12142 /// the parser read `[` and started to process a JSON array
12144 /// the parser read `]` and finished processing a JSON array
12146 /// the parser read a key of a value in an object
12148 /// the parser finished reading a JSON value
12152 template<typename BasicJsonType>
12153 using parser_callback_t =
12154 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12157 @brief syntax analysis
12159 This class implements a recursive descent parser.
12161 template<typename BasicJsonType, typename InputAdapterType>
12164 using number_integer_t = typename BasicJsonType::number_integer_t;
12165 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12166 using number_float_t = typename BasicJsonType::number_float_t;
12167 using string_t = typename BasicJsonType::string_t;
12168 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12169 using token_type = typename lexer_t::token_type;
12172 /// a parser reading from an input adapter
12173 explicit parser(InputAdapterType&& adapter,
12174 const parser_callback_t<BasicJsonType> cb = nullptr,
12175 const bool allow_exceptions_ = true,
12176 const bool skip_comments = false)
12178 , m_lexer(std::move(adapter), skip_comments)
12179 , allow_exceptions(allow_exceptions_)
12181 // read first token
12186 @brief public parser interface
12188 @param[in] strict whether to expect the last token to be EOF
12189 @param[in,out] result parsed JSON value
12191 @throw parse_error.101 in case of an unexpected token
12192 @throw parse_error.102 if to_unicode fails or surrogate error
12193 @throw parse_error.103 if to_unicode fails
12195 void parse(const bool strict, BasicJsonType& result)
12199 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12200 sax_parse_internal(&sdp);
12202 // in strict mode, input must be completely read
12203 if (strict && (get_token() != token_type::end_of_input))
12205 sdp.parse_error(m_lexer.get_position(),
12206 m_lexer.get_token_string(),
12207 parse_error::create(101, m_lexer.get_position(),
12208 exception_message(token_type::end_of_input, "value"), nullptr));
12211 // in case of an error, return discarded value
12212 if (sdp.is_errored())
12214 result = value_t::discarded;
12218 // set top-level value to null if it was discarded by the callback
12220 if (result.is_discarded())
12227 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12228 sax_parse_internal(&sdp);
12230 // in strict mode, input must be completely read
12231 if (strict && (get_token() != token_type::end_of_input))
12233 sdp.parse_error(m_lexer.get_position(),
12234 m_lexer.get_token_string(),
12235 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12238 // in case of an error, return discarded value
12239 if (sdp.is_errored())
12241 result = value_t::discarded;
12246 result.assert_invariant();
12250 @brief public accept interface
12252 @param[in] strict whether to expect the last token to be EOF
12253 @return whether the input is a proper JSON text
12255 bool accept(const bool strict = true)
12257 json_sax_acceptor<BasicJsonType> sax_acceptor;
12258 return sax_parse(&sax_acceptor, strict);
12261 template<typename SAX>
12262 JSON_HEDLEY_NON_NULL(2)
12263 bool sax_parse(SAX* sax, const bool strict = true)
12265 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12266 const bool result = sax_parse_internal(sax);
12268 // strict mode: next byte must be EOF
12269 if (result && strict && (get_token() != token_type::end_of_input))
12271 return sax->parse_error(m_lexer.get_position(),
12272 m_lexer.get_token_string(),
12273 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12280 template<typename SAX>
12281 JSON_HEDLEY_NON_NULL(2)
12282 bool sax_parse_internal(SAX* sax)
12284 // stack to remember the hierarchy of structured values we are parsing
12285 // true = array; false = object
12286 std::vector<bool> states;
12287 // value to avoid a goto (see comment where set to true)
12288 bool skip_to_state_evaluation = false;
12292 if (!skip_to_state_evaluation)
12294 // invariant: get_token() was called before each iteration
12295 switch (last_token)
12297 case token_type::begin_object:
12299 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12304 // closing } -> we are done
12305 if (get_token() == token_type::end_object)
12307 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12315 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12317 return sax->parse_error(m_lexer.get_position(),
12318 m_lexer.get_token_string(),
12319 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12321 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12326 // parse separator (:)
12327 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12329 return sax->parse_error(m_lexer.get_position(),
12330 m_lexer.get_token_string(),
12331 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12334 // remember we are now inside an object
12335 states.push_back(false);
12342 case token_type::begin_array:
12344 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12349 // closing ] -> we are done
12350 if (get_token() == token_type::end_array)
12352 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12359 // remember we are now inside an array
12360 states.push_back(true);
12362 // parse values (no need to call get_token)
12366 case token_type::value_float:
12368 const auto res = m_lexer.get_number_float();
12370 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12372 return sax->parse_error(m_lexer.get_position(),
12373 m_lexer.get_token_string(),
12374 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12377 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12385 case token_type::literal_false:
12387 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12394 case token_type::literal_null:
12396 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12403 case token_type::literal_true:
12405 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12412 case token_type::value_integer:
12414 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12421 case token_type::value_string:
12423 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12430 case token_type::value_unsigned:
12432 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12439 case token_type::parse_error:
12441 // using "uninitialized" to avoid "expected" message
12442 return sax->parse_error(m_lexer.get_position(),
12443 m_lexer.get_token_string(),
12444 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12447 case token_type::uninitialized:
12448 case token_type::end_array:
12449 case token_type::end_object:
12450 case token_type::name_separator:
12451 case token_type::value_separator:
12452 case token_type::end_of_input:
12453 case token_type::literal_or_value:
12454 default: // the last token was unexpected
12456 return sax->parse_error(m_lexer.get_position(),
12457 m_lexer.get_token_string(),
12458 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12464 skip_to_state_evaluation = false;
12467 // we reached this line after we successfully parsed a value
12468 if (states.empty())
12470 // empty stack: we reached the end of the hierarchy: done
12474 if (states.back()) // array
12476 // comma -> next value
12477 if (get_token() == token_type::value_separator)
12479 // parse a new value
12485 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12487 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12492 // We are done with this array. Before we can parse a
12493 // new value, we need to evaluate the new state first.
12494 // By setting skip_to_state_evaluation to false, we
12495 // are effectively jumping to the beginning of this if.
12496 JSON_ASSERT(!states.empty());
12498 skip_to_state_evaluation = true;
12502 return sax->parse_error(m_lexer.get_position(),
12503 m_lexer.get_token_string(),
12504 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12507 // states.back() is false -> object
12509 // comma -> next value
12510 if (get_token() == token_type::value_separator)
12513 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12515 return sax->parse_error(m_lexer.get_position(),
12516 m_lexer.get_token_string(),
12517 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12520 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12525 // parse separator (:)
12526 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12528 return sax->parse_error(m_lexer.get_position(),
12529 m_lexer.get_token_string(),
12530 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12539 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12541 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12546 // We are done with this object. Before we can parse a
12547 // new value, we need to evaluate the new state first.
12548 // By setting skip_to_state_evaluation to false, we
12549 // are effectively jumping to the beginning of this if.
12550 JSON_ASSERT(!states.empty());
12552 skip_to_state_evaluation = true;
12556 return sax->parse_error(m_lexer.get_position(),
12557 m_lexer.get_token_string(),
12558 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12562 /// get next token from lexer
12563 token_type get_token()
12565 return last_token = m_lexer.scan();
12568 std::string exception_message(const token_type expected, const std::string& context)
12570 std::string error_msg = "syntax error ";
12572 if (!context.empty())
12574 error_msg += concat("while parsing ", context, ' ');
12579 if (last_token == token_type::parse_error)
12581 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12582 m_lexer.get_token_string(), '\'');
12586 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12589 if (expected != token_type::uninitialized)
12591 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12598 /// callback function
12599 const parser_callback_t<BasicJsonType> callback = nullptr;
12600 /// the type of the last read token
12601 token_type last_token = token_type::uninitialized;
12604 /// whether to throw exceptions in case of errors
12605 const bool allow_exceptions = true;
12608 } // namespace detail
12609 NLOHMANN_JSON_NAMESPACE_END
12611 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
12612 // __ _____ _____ _____
12613 // __| | __| | | | JSON for Modern C++
12614 // | | |__ | | | | | | version 3.11.2
12615 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
12617 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12618 // SPDX-License-Identifier: MIT
12622 // #include <nlohmann/detail/abi_macros.hpp>
12624 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12625 // __ _____ _____ _____
12626 // __| | __| | | | JSON for Modern C++
12627 // | | |__ | | | | | | version 3.11.2
12628 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
12630 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12631 // SPDX-License-Identifier: MIT
12635 #include <cstddef> // ptrdiff_t
12636 #include <limits> // numeric_limits
12638 // #include <nlohmann/detail/macro_scope.hpp>
12641 NLOHMANN_JSON_NAMESPACE_BEGIN
12646 @brief an iterator for primitive JSON types
12648 This class models an iterator for primitive JSON types (boolean, number,
12649 string). It's only purpose is to allow the iterator/const_iterator classes
12650 to "iterate" over primitive values. Internally, the iterator is modeled by
12651 a `difference_type` variable. Value begin_value (`0`) models the begin,
12652 end_value (`1`) models past the end.
12654 class primitive_iterator_t
12657 using difference_type = std::ptrdiff_t;
12658 static constexpr difference_type begin_value = 0;
12659 static constexpr difference_type end_value = begin_value + 1;
12661 JSON_PRIVATE_UNLESS_TESTED:
12662 /// iterator as signed integer type
12663 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12666 constexpr difference_type get_value() const noexcept
12671 /// set iterator to a defined beginning
12672 void set_begin() noexcept
12674 m_it = begin_value;
12677 /// set iterator to a defined past the end
12678 void set_end() noexcept
12683 /// return whether the iterator can be dereferenced
12684 constexpr bool is_begin() const noexcept
12686 return m_it == begin_value;
12689 /// return whether the iterator is at end
12690 constexpr bool is_end() const noexcept
12692 return m_it == end_value;
12695 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12697 return lhs.m_it == rhs.m_it;
12700 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12702 return lhs.m_it < rhs.m_it;
12705 primitive_iterator_t operator+(difference_type n) noexcept
12707 auto result = *this;
12712 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12714 return lhs.m_it - rhs.m_it;
12717 primitive_iterator_t& operator++() noexcept
12723 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12725 auto result = *this;
12730 primitive_iterator_t& operator--() noexcept
12736 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12738 auto result = *this;
12743 primitive_iterator_t& operator+=(difference_type n) noexcept
12749 primitive_iterator_t& operator-=(difference_type n) noexcept
12756 } // namespace detail
12757 NLOHMANN_JSON_NAMESPACE_END
12760 NLOHMANN_JSON_NAMESPACE_BEGIN
12765 @brief an iterator value
12767 @note This structure could easily be a union, but MSVC currently does not allow
12768 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
12770 template<typename BasicJsonType> struct internal_iterator
12772 /// iterator for JSON objects
12773 typename BasicJsonType::object_t::iterator object_iterator {};
12774 /// iterator for JSON arrays
12775 typename BasicJsonType::array_t::iterator array_iterator {};
12776 /// generic iterator for all other types
12777 primitive_iterator_t primitive_iterator {};
12780 } // namespace detail
12781 NLOHMANN_JSON_NAMESPACE_END
12783 // #include <nlohmann/detail/iterators/iter_impl.hpp>
12784 // __ _____ _____ _____
12785 // __| | __| | | | JSON for Modern C++
12786 // | | |__ | | | | | | version 3.11.2
12787 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
12789 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
12790 // SPDX-License-Identifier: MIT
12794 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12795 #include <type_traits> // conditional, is_const, remove_const
12797 // #include <nlohmann/detail/exceptions.hpp>
12799 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
12801 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12803 // #include <nlohmann/detail/macro_scope.hpp>
12805 // #include <nlohmann/detail/meta/cpp_future.hpp>
12807 // #include <nlohmann/detail/meta/type_traits.hpp>
12809 // #include <nlohmann/detail/value_t.hpp>
12812 NLOHMANN_JSON_NAMESPACE_BEGIN
12816 // forward declare, to be able to friend it later on
12817 template<typename IteratorType> class iteration_proxy;
12818 template<typename IteratorType> class iteration_proxy_value;
12821 @brief a template for a bidirectional iterator for the @ref basic_json class
12822 This class implements a both iterators (iterator and const_iterator) for the
12823 @ref basic_json class.
12824 @note An iterator is called *initialized* when a pointer to a JSON value has
12825 been set (e.g., by a constructor or a copy assignment). If the iterator is
12826 default-constructed, it is *uninitialized* and most methods are undefined.
12827 **The library uses assertions to detect calls on uninitialized iterators.**
12828 @requirement The class satisfies the following concept requirements:
12830 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
12831 The iterator that can be moved can be moved in both directions (i.e.
12832 incremented and decremented).
12833 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
12834 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
12836 template<typename BasicJsonType>
12837 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12839 /// the iterator with BasicJsonType of different const-ness
12840 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12841 /// allow basic_json to access private members
12842 friend other_iter_impl;
12843 friend BasicJsonType;
12844 friend iteration_proxy<iter_impl>;
12845 friend iteration_proxy_value<iter_impl>;
12847 using object_t = typename BasicJsonType::object_t;
12848 using array_t = typename BasicJsonType::array_t;
12849 // make sure BasicJsonType is basic_json or const basic_json
12850 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
12851 "iter_impl only accepts (const) basic_json");
12852 // superficial check for the LegacyBidirectionalIterator named requirement
12853 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12854 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12855 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12858 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
12859 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
12860 /// A user-defined iterator should provide publicly accessible typedefs named
12861 /// iterator_category, value_type, difference_type, pointer, and reference.
12862 /// Note that value_type is required to be non-const, even for constant iterators.
12863 using iterator_category = std::bidirectional_iterator_tag;
12865 /// the type of the values when the iterator is dereferenced
12866 using value_type = typename BasicJsonType::value_type;
12867 /// a type to represent differences between iterators
12868 using difference_type = typename BasicJsonType::difference_type;
12869 /// defines a pointer to the type iterated over (value_type)
12870 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12871 typename BasicJsonType::const_pointer,
12872 typename BasicJsonType::pointer>::type;
12873 /// defines a reference to the type iterated over (value_type)
12875 typename std::conditional<std::is_const<BasicJsonType>::value,
12876 typename BasicJsonType::const_reference,
12877 typename BasicJsonType::reference>::type;
12879 iter_impl() = default;
12880 ~iter_impl() = default;
12881 iter_impl(iter_impl&&) noexcept = default;
12882 iter_impl& operator=(iter_impl&&) noexcept = default;
12885 @brief constructor for a given JSON instance
12886 @param[in] object pointer to a JSON object for this iterator
12887 @pre object != nullptr
12888 @post The iterator is initialized; i.e. `m_object != nullptr`.
12890 explicit iter_impl(pointer object) noexcept : m_object(object)
12892 JSON_ASSERT(m_object != nullptr);
12894 switch (m_object->m_data.m_type)
12896 case value_t::object:
12898 m_it.object_iterator = typename object_t::iterator();
12902 case value_t::array:
12904 m_it.array_iterator = typename array_t::iterator();
12908 case value_t::null:
12909 case value_t::string:
12910 case value_t::boolean:
12911 case value_t::number_integer:
12912 case value_t::number_unsigned:
12913 case value_t::number_float:
12914 case value_t::binary:
12915 case value_t::discarded:
12918 m_it.primitive_iterator = primitive_iterator_t();
12925 @note The conventional copy constructor and copy assignment are implicitly
12926 defined. Combined with the following converting constructor and
12927 assignment, they support: (1) copy from iterator to iterator, (2)
12928 copy from const iterator to const iterator, and (3) conversion from
12929 iterator to const iterator. However conversion from const iterator
12930 to iterator is not defined.
12934 @brief const copy constructor
12935 @param[in] other const iterator to copy from
12936 @note This copy constructor had to be defined explicitly to circumvent a bug
12937 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
12938 information refer to: https://github.com/nlohmann/json/issues/1608
12940 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
12941 : m_object(other.m_object), m_it(other.m_it)
12945 @brief converting assignment
12946 @param[in] other const iterator to copy from
12947 @return const/non-const iterator
12948 @note It is not checked whether @a other is initialized.
12950 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
12952 if (&other != this)
12954 m_object = other.m_object;
12961 @brief converting constructor
12962 @param[in] other non-const iterator to copy from
12963 @note It is not checked whether @a other is initialized.
12965 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
12966 : m_object(other.m_object), m_it(other.m_it)
12970 @brief converting assignment
12971 @param[in] other non-const iterator to copy from
12972 @return const/non-const iterator
12973 @note It is not checked whether @a other is initialized.
12975 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
12977 m_object = other.m_object;
12982 JSON_PRIVATE_UNLESS_TESTED:
12984 @brief set the iterator to the first value
12985 @pre The iterator is initialized; i.e. `m_object != nullptr`.
12987 void set_begin() noexcept
12989 JSON_ASSERT(m_object != nullptr);
12991 switch (m_object->m_data.m_type)
12993 case value_t::object:
12995 m_it.object_iterator = m_object->m_data.m_value.object->begin();
12999 case value_t::array:
13001 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13005 case value_t::null:
13007 // set to end so begin()==end() is true: null is empty
13008 m_it.primitive_iterator.set_end();
13012 case value_t::string:
13013 case value_t::boolean:
13014 case value_t::number_integer:
13015 case value_t::number_unsigned:
13016 case value_t::number_float:
13017 case value_t::binary:
13018 case value_t::discarded:
13021 m_it.primitive_iterator.set_begin();
13028 @brief set the iterator past the last value
13029 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13031 void set_end() noexcept
13033 JSON_ASSERT(m_object != nullptr);
13035 switch (m_object->m_data.m_type)
13037 case value_t::object:
13039 m_it.object_iterator = m_object->m_data.m_value.object->end();
13043 case value_t::array:
13045 m_it.array_iterator = m_object->m_data.m_value.array->end();
13049 case value_t::null:
13050 case value_t::string:
13051 case value_t::boolean:
13052 case value_t::number_integer:
13053 case value_t::number_unsigned:
13054 case value_t::number_float:
13055 case value_t::binary:
13056 case value_t::discarded:
13059 m_it.primitive_iterator.set_end();
13067 @brief return a reference to the value pointed to by the iterator
13068 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13070 reference operator*() const
13072 JSON_ASSERT(m_object != nullptr);
13074 switch (m_object->m_data.m_type)
13076 case value_t::object:
13078 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13079 return m_it.object_iterator->second;
13082 case value_t::array:
13084 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13085 return *m_it.array_iterator;
13088 case value_t::null:
13089 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13091 case value_t::string:
13092 case value_t::boolean:
13093 case value_t::number_integer:
13094 case value_t::number_unsigned:
13095 case value_t::number_float:
13096 case value_t::binary:
13097 case value_t::discarded:
13100 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13105 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13111 @brief dereference the iterator
13112 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13114 pointer operator->() const
13116 JSON_ASSERT(m_object != nullptr);
13118 switch (m_object->m_data.m_type)
13120 case value_t::object:
13122 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13123 return &(m_it.object_iterator->second);
13126 case value_t::array:
13128 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13129 return &*m_it.array_iterator;
13132 case value_t::null:
13133 case value_t::string:
13134 case value_t::boolean:
13135 case value_t::number_integer:
13136 case value_t::number_unsigned:
13137 case value_t::number_float:
13138 case value_t::binary:
13139 case value_t::discarded:
13142 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13147 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13153 @brief post-increment (it++)
13154 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13156 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13158 auto result = *this;
13164 @brief pre-increment (++it)
13165 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13167 iter_impl& operator++()
13169 JSON_ASSERT(m_object != nullptr);
13171 switch (m_object->m_data.m_type)
13173 case value_t::object:
13175 std::advance(m_it.object_iterator, 1);
13179 case value_t::array:
13181 std::advance(m_it.array_iterator, 1);
13185 case value_t::null:
13186 case value_t::string:
13187 case value_t::boolean:
13188 case value_t::number_integer:
13189 case value_t::number_unsigned:
13190 case value_t::number_float:
13191 case value_t::binary:
13192 case value_t::discarded:
13195 ++m_it.primitive_iterator;
13204 @brief post-decrement (it--)
13205 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13207 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13209 auto result = *this;
13215 @brief pre-decrement (--it)
13216 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13218 iter_impl& operator--()
13220 JSON_ASSERT(m_object != nullptr);
13222 switch (m_object->m_data.m_type)
13224 case value_t::object:
13226 std::advance(m_it.object_iterator, -1);
13230 case value_t::array:
13232 std::advance(m_it.array_iterator, -1);
13236 case value_t::null:
13237 case value_t::string:
13238 case value_t::boolean:
13239 case value_t::number_integer:
13240 case value_t::number_unsigned:
13241 case value_t::number_float:
13242 case value_t::binary:
13243 case value_t::discarded:
13246 --m_it.primitive_iterator;
13255 @brief comparison: equal
13256 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13258 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13259 bool operator==(const IterImpl& other) const
13261 // if objects are not the same, the comparison is undefined
13262 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13264 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13267 JSON_ASSERT(m_object != nullptr);
13269 switch (m_object->m_data.m_type)
13271 case value_t::object:
13272 return (m_it.object_iterator == other.m_it.object_iterator);
13274 case value_t::array:
13275 return (m_it.array_iterator == other.m_it.array_iterator);
13277 case value_t::null:
13278 case value_t::string:
13279 case value_t::boolean:
13280 case value_t::number_integer:
13281 case value_t::number_unsigned:
13282 case value_t::number_float:
13283 case value_t::binary:
13284 case value_t::discarded:
13286 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13291 @brief comparison: not equal
13292 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13294 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13295 bool operator!=(const IterImpl& other) const
13297 return !operator==(other);
13301 @brief comparison: smaller
13302 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13304 bool operator<(const iter_impl& other) const
13306 // if objects are not the same, the comparison is undefined
13307 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13309 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13312 JSON_ASSERT(m_object != nullptr);
13314 switch (m_object->m_data.m_type)
13316 case value_t::object:
13317 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13319 case value_t::array:
13320 return (m_it.array_iterator < other.m_it.array_iterator);
13322 case value_t::null:
13323 case value_t::string:
13324 case value_t::boolean:
13325 case value_t::number_integer:
13326 case value_t::number_unsigned:
13327 case value_t::number_float:
13328 case value_t::binary:
13329 case value_t::discarded:
13331 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13336 @brief comparison: less than or equal
13337 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13339 bool operator<=(const iter_impl& other) const
13341 return !other.operator < (*this);
13345 @brief comparison: greater than
13346 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13348 bool operator>(const iter_impl& other) const
13350 return !operator<=(other);
13354 @brief comparison: greater than or equal
13355 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13357 bool operator>=(const iter_impl& other) const
13359 return !operator<(other);
13363 @brief add to iterator
13364 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13366 iter_impl& operator+=(difference_type i)
13368 JSON_ASSERT(m_object != nullptr);
13370 switch (m_object->m_data.m_type)
13372 case value_t::object:
13373 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13375 case value_t::array:
13377 std::advance(m_it.array_iterator, i);
13381 case value_t::null:
13382 case value_t::string:
13383 case value_t::boolean:
13384 case value_t::number_integer:
13385 case value_t::number_unsigned:
13386 case value_t::number_float:
13387 case value_t::binary:
13388 case value_t::discarded:
13391 m_it.primitive_iterator += i;
13400 @brief subtract from iterator
13401 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13403 iter_impl& operator-=(difference_type i)
13405 return operator+=(-i);
13409 @brief add to iterator
13410 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13412 iter_impl operator+(difference_type i) const
13414 auto result = *this;
13420 @brief addition of distance and iterator
13421 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13423 friend iter_impl operator+(difference_type i, const iter_impl& it)
13431 @brief subtract from iterator
13432 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13434 iter_impl operator-(difference_type i) const
13436 auto result = *this;
13442 @brief return difference
13443 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13445 difference_type operator-(const iter_impl& other) const
13447 JSON_ASSERT(m_object != nullptr);
13449 switch (m_object->m_data.m_type)
13451 case value_t::object:
13452 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13454 case value_t::array:
13455 return m_it.array_iterator - other.m_it.array_iterator;
13457 case value_t::null:
13458 case value_t::string:
13459 case value_t::boolean:
13460 case value_t::number_integer:
13461 case value_t::number_unsigned:
13462 case value_t::number_float:
13463 case value_t::binary:
13464 case value_t::discarded:
13466 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13471 @brief access to successor
13472 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13474 reference operator[](difference_type n) const
13476 JSON_ASSERT(m_object != nullptr);
13478 switch (m_object->m_data.m_type)
13480 case value_t::object:
13481 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13483 case value_t::array:
13484 return *std::next(m_it.array_iterator, n);
13486 case value_t::null:
13487 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13489 case value_t::string:
13490 case value_t::boolean:
13491 case value_t::number_integer:
13492 case value_t::number_unsigned:
13493 case value_t::number_float:
13494 case value_t::binary:
13495 case value_t::discarded:
13498 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13503 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13509 @brief return the key of an object iterator
13510 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13512 const typename object_t::key_type& key() const
13514 JSON_ASSERT(m_object != nullptr);
13516 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13518 return m_it.object_iterator->first;
13521 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13525 @brief return the value of an iterator
13526 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13528 reference value() const
13530 return operator*();
13533 JSON_PRIVATE_UNLESS_TESTED:
13534 /// associated JSON instance
13535 pointer m_object = nullptr;
13536 /// the actual iterator of the associated instance
13537 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
13540 } // namespace detail
13541 NLOHMANN_JSON_NAMESPACE_END
13543 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13545 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13546 // __ _____ _____ _____
13547 // __| | __| | | | JSON for Modern C++
13548 // | | |__ | | | | | | version 3.11.2
13549 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
13551 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13552 // SPDX-License-Identifier: MIT
13556 #include <cstddef> // ptrdiff_t
13557 #include <iterator> // reverse_iterator
13558 #include <utility> // declval
13560 // #include <nlohmann/detail/abi_macros.hpp>
13563 NLOHMANN_JSON_NAMESPACE_BEGIN
13567 //////////////////////
13568 // reverse_iterator //
13569 //////////////////////
13572 @brief a template for a reverse iterator class
13574 @tparam Base the base iterator type to reverse. Valid types are @ref
13575 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
13576 create @ref const_reverse_iterator).
13578 @requirement The class satisfies the following concept requirements:
13580 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13581 The iterator that can be moved can be moved in both directions (i.e.
13582 incremented and decremented).
13583 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
13584 It is possible to write to the pointed-to element (only if @a Base is
13587 @since version 1.0.0
13589 template<typename Base>
13590 class json_reverse_iterator : public std::reverse_iterator<Base>
13593 using difference_type = std::ptrdiff_t;
13594 /// shortcut to the reverse iterator adapter
13595 using base_iterator = std::reverse_iterator<Base>;
13596 /// the reference type for the pointed-to element
13597 using reference = typename Base::reference;
13599 /// create reverse iterator from iterator
13600 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13601 : base_iterator(it) {}
13603 /// create reverse iterator from base class
13604 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13606 /// post-increment (it++)
13607 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13609 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13612 /// pre-increment (++it)
13613 json_reverse_iterator& operator++()
13615 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13618 /// post-decrement (it--)
13619 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13621 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13624 /// pre-decrement (--it)
13625 json_reverse_iterator& operator--()
13627 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13630 /// add to iterator
13631 json_reverse_iterator& operator+=(difference_type i)
13633 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13636 /// add to iterator
13637 json_reverse_iterator operator+(difference_type i) const
13639 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13642 /// subtract from iterator
13643 json_reverse_iterator operator-(difference_type i) const
13645 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13648 /// return difference
13649 difference_type operator-(const json_reverse_iterator& other) const
13651 return base_iterator(*this) - base_iterator(other);
13654 /// access to successor
13655 reference operator[](difference_type n) const
13657 return *(this->operator+(n));
13660 /// return the key of an object iterator
13661 auto key() const -> decltype(std::declval<Base>().key())
13663 auto it = --this->base();
13667 /// return the value of an iterator
13668 reference value() const
13670 auto it = --this->base();
13671 return it.operator * ();
13675 } // namespace detail
13676 NLOHMANN_JSON_NAMESPACE_END
13678 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13680 // #include <nlohmann/detail/json_custom_base_class.hpp>
13683 #include <type_traits> // conditional, is_same
13685 // #include <nlohmann/detail/abi_macros.hpp>
13688 NLOHMANN_JSON_NAMESPACE_BEGIN
13693 @brief Default base class of the @ref basic_json class.
13695 So that the correct implementations of the copy / move ctors / assign operators
13696 of @ref basic_json do not require complex case distinctions
13697 (no base class / custom base class used as customization point),
13698 @ref basic_json always has a base class.
13699 By default, this class is used because it is empty and thus has no effect
13700 on the behavior of @ref basic_json.
13702 struct json_default_base {};
13705 using json_base_class = typename std::conditional <
13706 std::is_same<T, void>::value,
13711 } // namespace detail
13712 NLOHMANN_JSON_NAMESPACE_END
13714 // #include <nlohmann/detail/json_pointer.hpp>
13715 // __ _____ _____ _____
13716 // __| | __| | | | JSON for Modern C++
13717 // | | |__ | | | | | | version 3.11.2
13718 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
13720 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
13721 // SPDX-License-Identifier: MIT
13725 #include <algorithm> // all_of
13726 #include <cctype> // isdigit
13727 #include <cerrno> // errno, ERANGE
13728 #include <cstdlib> // strtoull
13730 #include <iosfwd> // ostream
13731 #endif // JSON_NO_IO
13732 #include <limits> // max
13733 #include <numeric> // accumulate
13734 #include <string> // string
13735 #include <utility> // move
13736 #include <vector> // vector
13738 // #include <nlohmann/detail/exceptions.hpp>
13740 // #include <nlohmann/detail/macro_scope.hpp>
13742 // #include <nlohmann/detail/string_concat.hpp>
13744 // #include <nlohmann/detail/string_escape.hpp>
13746 // #include <nlohmann/detail/value_t.hpp>
13749 NLOHMANN_JSON_NAMESPACE_BEGIN
13751 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
13752 /// @sa https://json.nlohmann.me/api/json_pointer/
13753 template<typename RefStringType>
13756 // allow basic_json to access private members
13757 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13758 friend class basic_json;
13761 friend class json_pointer;
13763 template<typename T>
13764 struct string_t_helper
13769 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13770 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13772 using type = StringType;
13776 // for backwards compatibility accept BasicJsonType
13777 using string_t = typename string_t_helper<RefStringType>::type;
13779 /// @brief create JSON pointer
13780 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
13781 explicit json_pointer(const string_t& s = "")
13782 : reference_tokens(split(s))
13785 /// @brief return a string representation of the JSON pointer
13786 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
13787 string_t to_string() const
13789 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13791 [](const string_t& a, const string_t& b)
13793 return detail::concat(a, '/', detail::escape(b));
13797 /// @brief return a string representation of the JSON pointer
13798 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
13799 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13800 operator string_t() const
13802 return to_string();
13806 /// @brief write string representation of the JSON pointer to stream
13807 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
13808 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13810 o << ptr.to_string();
13815 /// @brief append another JSON pointer at the end of this JSON pointer
13816 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13817 json_pointer& operator/=(const json_pointer& ptr)
13819 reference_tokens.insert(reference_tokens.end(),
13820 ptr.reference_tokens.begin(),
13821 ptr.reference_tokens.end());
13825 /// @brief append an unescaped reference token at the end of this JSON pointer
13826 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13827 json_pointer& operator/=(string_t token)
13829 push_back(std::move(token));
13833 /// @brief append an array index at the end of this JSON pointer
13834 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
13835 json_pointer& operator/=(std::size_t array_idx)
13837 return *this /= std::to_string(array_idx);
13840 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
13841 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13842 friend json_pointer operator/(const json_pointer& lhs,
13843 const json_pointer& rhs)
13845 return json_pointer(lhs) /= rhs;
13848 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
13849 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13850 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13852 return json_pointer(lhs) /= std::move(token);
13855 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
13856 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
13857 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13859 return json_pointer(lhs) /= array_idx;
13862 /// @brief returns the parent of this JSON pointer
13863 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
13864 json_pointer parent_pointer() const
13871 json_pointer res = *this;
13876 /// @brief remove last reference token
13877 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
13880 if (JSON_HEDLEY_UNLIKELY(empty()))
13882 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13885 reference_tokens.pop_back();
13888 /// @brief return last reference token
13889 /// @sa https://json.nlohmann.me/api/json_pointer/back/
13890 const string_t& back() const
13892 if (JSON_HEDLEY_UNLIKELY(empty()))
13894 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13897 return reference_tokens.back();
13900 /// @brief append an unescaped token at the end of the reference pointer
13901 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13902 void push_back(const string_t& token)
13904 reference_tokens.push_back(token);
13907 /// @brief append an unescaped token at the end of the reference pointer
13908 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
13909 void push_back(string_t&& token)
13911 reference_tokens.push_back(std::move(token));
13914 /// @brief return whether pointer points to the root document
13915 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
13916 bool empty() const noexcept
13918 return reference_tokens.empty();
13923 @param[in] s reference token to be converted into an array index
13925 @return integer representation of @a s
13927 @throw parse_error.106 if an array index begins with '0'
13928 @throw parse_error.109 if an array index begins not with a digit
13929 @throw out_of_range.404 if string @a s could not be converted to an integer
13930 @throw out_of_range.410 if an array index exceeds size_type
13932 template<typename BasicJsonType>
13933 static typename BasicJsonType::size_type array_index(const string_t& s)
13935 using size_type = typename BasicJsonType::size_type;
13937 // error condition (cf. RFC 6901, Sect. 4)
13938 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
13940 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
13943 // error condition (cf. RFC 6901, Sect. 4)
13944 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
13946 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
13949 const char* p = s.c_str();
13950 char* p_end = nullptr;
13951 errno = 0; // strtoull doesn't reset errno
13952 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
13953 if (p == p_end // invalid input or empty string
13954 || errno == ERANGE // out of range
13955 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
13957 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
13960 // only triggered on special platforms (like 32bit), see also
13961 // https://github.com/nlohmann/json/pull/2203
13962 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
13964 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
13967 return static_cast<size_type>(res);
13970 JSON_PRIVATE_UNLESS_TESTED:
13971 json_pointer top() const
13973 if (JSON_HEDLEY_UNLIKELY(empty()))
13975 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13978 json_pointer result = *this;
13979 result.reference_tokens = {reference_tokens[0]};
13985 @brief create and return a reference to the pointed to value
13987 @complexity Linear in the number of reference tokens.
13989 @throw parse_error.109 if array index is not a number
13990 @throw type_error.313 if value cannot be unflattened
13992 template<typename BasicJsonType>
13993 BasicJsonType& get_and_create(BasicJsonType& j) const
13997 // in case no reference tokens exist, return a reference to the JSON value
13998 // j which will be overwritten by a primitive value
13999 for (const auto& reference_token : reference_tokens)
14001 switch (result->type())
14003 case detail::value_t::null:
14005 if (reference_token == "0")
14007 // start a new array if reference token is 0
14008 result = &result->operator[](0);
14012 // start a new object otherwise
14013 result = &result->operator[](reference_token);
14018 case detail::value_t::object:
14020 // create an entry in the object
14021 result = &result->operator[](reference_token);
14025 case detail::value_t::array:
14027 // create an entry in the array
14028 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14033 The following code is only reached if there exists a reference
14034 token _and_ the current value is primitive. In this case, we have
14035 an error situation, because primitive values may only occur as
14036 single value; that is, with an empty list of reference tokens.
14038 case detail::value_t::string:
14039 case detail::value_t::boolean:
14040 case detail::value_t::number_integer:
14041 case detail::value_t::number_unsigned:
14042 case detail::value_t::number_float:
14043 case detail::value_t::binary:
14044 case detail::value_t::discarded:
14046 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14054 @brief return a reference to the pointed to value
14056 @note This version does not throw if a value is not present, but tries to
14057 create nested values instead. For instance, calling this function
14058 with pointer `"/this/that"` on a null value is equivalent to calling
14059 `operator[]("this").operator[]("that")` on that value, effectively
14060 changing the null value to an object.
14062 @param[in] ptr a JSON value
14064 @return reference to the JSON value pointed to by the JSON pointer
14066 @complexity Linear in the length of the JSON pointer.
14068 @throw parse_error.106 if an array index begins with '0'
14069 @throw parse_error.109 if an array index was not a number
14070 @throw out_of_range.404 if the JSON pointer can not be resolved
14072 template<typename BasicJsonType>
14073 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14075 for (const auto& reference_token : reference_tokens)
14077 // convert null values to arrays or objects before continuing
14078 if (ptr->is_null())
14080 // check if reference token is a number
14082 std::all_of(reference_token.begin(), reference_token.end(),
14083 [](const unsigned char x)
14085 return std::isdigit(x);
14088 // change value to array for numbers or "-" or to object otherwise
14089 *ptr = (nums || reference_token == "-")
14090 ? detail::value_t::array
14091 : detail::value_t::object;
14094 switch (ptr->type())
14096 case detail::value_t::object:
14098 // use unchecked object access
14099 ptr = &ptr->operator[](reference_token);
14103 case detail::value_t::array:
14105 if (reference_token == "-")
14107 // explicitly treat "-" as index beyond the end
14108 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14112 // convert array index to number; unchecked access
14113 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14118 case detail::value_t::null:
14119 case detail::value_t::string:
14120 case detail::value_t::boolean:
14121 case detail::value_t::number_integer:
14122 case detail::value_t::number_unsigned:
14123 case detail::value_t::number_float:
14124 case detail::value_t::binary:
14125 case detail::value_t::discarded:
14127 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14135 @throw parse_error.106 if an array index begins with '0'
14136 @throw parse_error.109 if an array index was not a number
14137 @throw out_of_range.402 if the array index '-' is used
14138 @throw out_of_range.404 if the JSON pointer can not be resolved
14140 template<typename BasicJsonType>
14141 BasicJsonType& get_checked(BasicJsonType* ptr) const
14143 for (const auto& reference_token : reference_tokens)
14145 switch (ptr->type())
14147 case detail::value_t::object:
14149 // note: at performs range check
14150 ptr = &ptr->at(reference_token);
14154 case detail::value_t::array:
14156 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14158 // "-" always fails the range check
14159 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14160 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14161 ") is out of range"), ptr));
14164 // note: at performs range check
14165 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14169 case detail::value_t::null:
14170 case detail::value_t::string:
14171 case detail::value_t::boolean:
14172 case detail::value_t::number_integer:
14173 case detail::value_t::number_unsigned:
14174 case detail::value_t::number_float:
14175 case detail::value_t::binary:
14176 case detail::value_t::discarded:
14178 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14186 @brief return a const reference to the pointed to value
14188 @param[in] ptr a JSON value
14190 @return const reference to the JSON value pointed to by the JSON
14193 @throw parse_error.106 if an array index begins with '0'
14194 @throw parse_error.109 if an array index was not a number
14195 @throw out_of_range.402 if the array index '-' is used
14196 @throw out_of_range.404 if the JSON pointer can not be resolved
14198 template<typename BasicJsonType>
14199 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14201 for (const auto& reference_token : reference_tokens)
14203 switch (ptr->type())
14205 case detail::value_t::object:
14207 // use unchecked object access
14208 ptr = &ptr->operator[](reference_token);
14212 case detail::value_t::array:
14214 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14216 // "-" cannot be used for const access
14217 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14220 // use unchecked array access
14221 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14225 case detail::value_t::null:
14226 case detail::value_t::string:
14227 case detail::value_t::boolean:
14228 case detail::value_t::number_integer:
14229 case detail::value_t::number_unsigned:
14230 case detail::value_t::number_float:
14231 case detail::value_t::binary:
14232 case detail::value_t::discarded:
14234 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14242 @throw parse_error.106 if an array index begins with '0'
14243 @throw parse_error.109 if an array index was not a number
14244 @throw out_of_range.402 if the array index '-' is used
14245 @throw out_of_range.404 if the JSON pointer can not be resolved
14247 template<typename BasicJsonType>
14248 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14250 for (const auto& reference_token : reference_tokens)
14252 switch (ptr->type())
14254 case detail::value_t::object:
14256 // note: at performs range check
14257 ptr = &ptr->at(reference_token);
14261 case detail::value_t::array:
14263 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14265 // "-" always fails the range check
14266 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14267 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14268 ") is out of range"), ptr));
14271 // note: at performs range check
14272 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14276 case detail::value_t::null:
14277 case detail::value_t::string:
14278 case detail::value_t::boolean:
14279 case detail::value_t::number_integer:
14280 case detail::value_t::number_unsigned:
14281 case detail::value_t::number_float:
14282 case detail::value_t::binary:
14283 case detail::value_t::discarded:
14285 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14293 @throw parse_error.106 if an array index begins with '0'
14294 @throw parse_error.109 if an array index was not a number
14296 template<typename BasicJsonType>
14297 bool contains(const BasicJsonType* ptr) const
14299 for (const auto& reference_token : reference_tokens)
14301 switch (ptr->type())
14303 case detail::value_t::object:
14305 if (!ptr->contains(reference_token))
14307 // we did not find the key in the object
14311 ptr = &ptr->operator[](reference_token);
14315 case detail::value_t::array:
14317 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14319 // "-" always fails the range check
14322 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14327 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14329 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14331 // first char should be between '1' and '9'
14334 for (std::size_t i = 1; i < reference_token.size(); i++)
14336 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14338 // other char should be between '0' and '9'
14344 const auto idx = array_index<BasicJsonType>(reference_token);
14345 if (idx >= ptr->size())
14347 // index out of range
14351 ptr = &ptr->operator[](idx);
14355 case detail::value_t::null:
14356 case detail::value_t::string:
14357 case detail::value_t::boolean:
14358 case detail::value_t::number_integer:
14359 case detail::value_t::number_unsigned:
14360 case detail::value_t::number_float:
14361 case detail::value_t::binary:
14362 case detail::value_t::discarded:
14365 // we do not expect primitive values if there is still a
14366 // reference token to process
14372 // no reference token left means we found a primitive value
14377 @brief split the string input to reference tokens
14379 @note This function is only called by the json_pointer constructor.
14380 All exceptions below are documented there.
14382 @throw parse_error.107 if the pointer is not empty or begins with '/'
14383 @throw parse_error.108 if character '~' is not followed by '0' or '1'
14385 static std::vector<string_t> split(const string_t& reference_string)
14387 std::vector<string_t> result;
14389 // special case: empty reference string -> no reference tokens
14390 if (reference_string.empty())
14395 // check if nonempty reference string begins with slash
14396 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14398 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14401 // extract the reference tokens:
14402 // - slash: position of the last read slash (or end of string)
14403 // - start: position after the previous slash
14405 // search for the first slash after the first character
14406 std::size_t slash = reference_string.find_first_of('/', 1),
14407 // set the beginning of the first reference token
14409 // we can stop if start == 0 (if slash == string_t::npos)
14411 // set the beginning of the next reference token
14412 // (will eventually be 0 if slash == string_t::npos)
14413 start = (slash == string_t::npos) ? 0 : slash + 1,
14415 slash = reference_string.find_first_of('/', start))
14417 // use the text between the beginning of the reference token
14418 // (start) and the last slash (slash).
14419 auto reference_token = reference_string.substr(start, slash - start);
14421 // check reference tokens are properly escaped
14422 for (std::size_t pos = reference_token.find_first_of('~');
14423 pos != string_t::npos;
14424 pos = reference_token.find_first_of('~', pos + 1))
14426 JSON_ASSERT(reference_token[pos] == '~');
14428 // ~ must be followed by 0 or 1
14429 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14430 (reference_token[pos + 1] != '0' &&
14431 reference_token[pos + 1] != '1')))
14433 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14437 // finally, store the reference token
14438 detail::unescape(reference_token);
14439 result.push_back(reference_token);
14447 @param[in] reference_string the reference string to the current value
14448 @param[in] value the value to consider
14449 @param[in,out] result the result object to insert values to
14451 @note Empty objects or arrays are flattened to `null`.
14453 template<typename BasicJsonType>
14454 static void flatten(const string_t& reference_string,
14455 const BasicJsonType& value,
14456 BasicJsonType& result)
14458 switch (value.type())
14460 case detail::value_t::array:
14462 if (value.m_data.m_value.array->empty())
14464 // flatten empty array as null
14465 result[reference_string] = nullptr;
14469 // iterate array and use index as reference string
14470 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14472 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14473 value.m_data.m_value.array->operator[](i), result);
14479 case detail::value_t::object:
14481 if (value.m_data.m_value.object->empty())
14483 // flatten empty object as null
14484 result[reference_string] = nullptr;
14488 // iterate object and use keys as reference string
14489 for (const auto& element : *value.m_data.m_value.object)
14491 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14497 case detail::value_t::null:
14498 case detail::value_t::string:
14499 case detail::value_t::boolean:
14500 case detail::value_t::number_integer:
14501 case detail::value_t::number_unsigned:
14502 case detail::value_t::number_float:
14503 case detail::value_t::binary:
14504 case detail::value_t::discarded:
14507 // add primitive value with its reference string
14508 result[reference_string] = value;
14515 @param[in] value flattened JSON
14517 @return unflattened JSON
14519 @throw parse_error.109 if array index is not a number
14520 @throw type_error.314 if value is not an object
14521 @throw type_error.315 if object values are not primitive
14522 @throw type_error.313 if value cannot be unflattened
14524 template<typename BasicJsonType>
14525 static BasicJsonType
14526 unflatten(const BasicJsonType& value)
14528 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14530 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14533 BasicJsonType result;
14535 // iterate the JSON object values
14536 for (const auto& element : *value.m_data.m_value.object)
14538 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14540 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14543 // assign value to reference pointed to by JSON pointer; Note that if
14544 // the JSON pointer is "" (i.e., points to the whole value), function
14545 // get_and_create returns a reference to result itself. An assignment
14546 // will then create a primitive value.
14547 json_pointer(element.first).get_and_create(result) = element.second;
14553 // can't use conversion operator because of ambiguity
14554 json_pointer<string_t> convert() const&
14556 json_pointer<string_t> result;
14557 result.reference_tokens = reference_tokens;
14561 json_pointer<string_t> convert()&&
14563 json_pointer<string_t> result;
14564 result.reference_tokens = std::move(reference_tokens);
14569 #if JSON_HAS_THREE_WAY_COMPARISON
14570 /// @brief compares two JSON pointers for equality
14571 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14572 template<typename RefStringTypeRhs>
14573 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14575 return reference_tokens == rhs.reference_tokens;
14578 /// @brief compares JSON pointer and string for equality
14579 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14580 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14581 bool operator==(const string_t& rhs) const
14583 return *this == json_pointer(rhs);
14586 /// @brief 3-way compares two JSON pointers
14587 template<typename RefStringTypeRhs>
14588 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14590 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14593 /// @brief compares two JSON pointers for equality
14594 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14595 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14596 // NOLINTNEXTLINE(readability-redundant-declaration)
14597 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14598 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14600 /// @brief compares JSON pointer and string for equality
14601 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14602 template<typename RefStringTypeLhs, typename StringType>
14603 // NOLINTNEXTLINE(readability-redundant-declaration)
14604 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14605 const StringType& rhs);
14607 /// @brief compares string and JSON pointer for equality
14608 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14609 template<typename RefStringTypeRhs, typename StringType>
14610 // NOLINTNEXTLINE(readability-redundant-declaration)
14611 friend bool operator==(const StringType& lhs,
14612 const json_pointer<RefStringTypeRhs>& rhs);
14614 /// @brief compares two JSON pointers for inequality
14615 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14616 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14617 // NOLINTNEXTLINE(readability-redundant-declaration)
14618 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14619 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14621 /// @brief compares JSON pointer and string for inequality
14622 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14623 template<typename RefStringTypeLhs, typename StringType>
14624 // NOLINTNEXTLINE(readability-redundant-declaration)
14625 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14626 const StringType& rhs);
14628 /// @brief compares string and JSON pointer for inequality
14629 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14630 template<typename RefStringTypeRhs, typename StringType>
14631 // NOLINTNEXTLINE(readability-redundant-declaration)
14632 friend bool operator!=(const StringType& lhs,
14633 const json_pointer<RefStringTypeRhs>& rhs);
14635 /// @brief compares two JSON pointer for less-than
14636 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14637 // NOLINTNEXTLINE(readability-redundant-declaration)
14638 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14639 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14643 /// the reference tokens
14644 std::vector<string_t> reference_tokens;
14647 #if !JSON_HAS_THREE_WAY_COMPARISON
14648 // functions cannot be defined inside class due to ODR violations
14649 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14650 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14651 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14653 return lhs.reference_tokens == rhs.reference_tokens;
14656 template<typename RefStringTypeLhs,
14657 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14658 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14659 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14660 const StringType& rhs)
14662 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14665 template<typename RefStringTypeRhs,
14666 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14667 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14668 inline bool operator==(const StringType& lhs,
14669 const json_pointer<RefStringTypeRhs>& rhs)
14671 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14674 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14675 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14676 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14678 return !(lhs == rhs);
14681 template<typename RefStringTypeLhs,
14682 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14683 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14684 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14685 const StringType& rhs)
14687 return !(lhs == rhs);
14690 template<typename RefStringTypeRhs,
14691 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14692 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14693 inline bool operator!=(const StringType& lhs,
14694 const json_pointer<RefStringTypeRhs>& rhs)
14696 return !(lhs == rhs);
14699 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14700 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14701 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14703 return lhs.reference_tokens < rhs.reference_tokens;
14707 NLOHMANN_JSON_NAMESPACE_END
14709 // #include <nlohmann/detail/json_ref.hpp>
14710 // __ _____ _____ _____
14711 // __| | __| | | | JSON for Modern C++
14712 // | | |__ | | | | | | version 3.11.2
14713 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
14715 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14716 // SPDX-License-Identifier: MIT
14720 #include <initializer_list>
14723 // #include <nlohmann/detail/abi_macros.hpp>
14725 // #include <nlohmann/detail/meta/type_traits.hpp>
14728 NLOHMANN_JSON_NAMESPACE_BEGIN
14732 template<typename BasicJsonType>
14736 using value_type = BasicJsonType;
14738 json_ref(value_type&& value)
14739 : owned_value(std::move(value))
14742 json_ref(const value_type& value)
14743 : value_ref(&value)
14746 json_ref(std::initializer_list<json_ref> init)
14747 : owned_value(init)
14752 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14753 json_ref(Args && ... args)
14754 : owned_value(std::forward<Args>(args)...)
14757 // class should be movable only
14758 json_ref(json_ref&&) noexcept = default;
14759 json_ref(const json_ref&) = delete;
14760 json_ref& operator=(const json_ref&) = delete;
14761 json_ref& operator=(json_ref&&) = delete;
14762 ~json_ref() = default;
14764 value_type moved_or_copied() const
14766 if (value_ref == nullptr)
14768 return std::move(owned_value);
14773 value_type const& operator*() const
14775 return value_ref ? *value_ref : owned_value;
14778 value_type const* operator->() const
14784 mutable value_type owned_value = nullptr;
14785 value_type const* value_ref = nullptr;
14788 } // namespace detail
14789 NLOHMANN_JSON_NAMESPACE_END
14791 // #include <nlohmann/detail/macro_scope.hpp>
14793 // #include <nlohmann/detail/string_concat.hpp>
14795 // #include <nlohmann/detail/string_escape.hpp>
14797 // #include <nlohmann/detail/meta/cpp_future.hpp>
14799 // #include <nlohmann/detail/meta/type_traits.hpp>
14801 // #include <nlohmann/detail/output/binary_writer.hpp>
14802 // __ _____ _____ _____
14803 // __| | __| | | | JSON for Modern C++
14804 // | | |__ | | | | | | version 3.11.2
14805 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
14807 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14808 // SPDX-License-Identifier: MIT
14812 #include <algorithm> // reverse
14813 #include <array> // array
14814 #include <map> // map
14815 #include <cmath> // isnan, isinf
14816 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14817 #include <cstring> // memcpy
14818 #include <limits> // numeric_limits
14819 #include <string> // string
14820 #include <utility> // move
14821 #include <vector> // vector
14823 // #include <nlohmann/detail/input/binary_reader.hpp>
14825 // #include <nlohmann/detail/macro_scope.hpp>
14827 // #include <nlohmann/detail/output/output_adapters.hpp>
14828 // __ _____ _____ _____
14829 // __| | __| | | | JSON for Modern C++
14830 // | | |__ | | | | | | version 3.11.2
14831 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
14833 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
14834 // SPDX-License-Identifier: MIT
14838 #include <algorithm> // copy
14839 #include <cstddef> // size_t
14840 #include <iterator> // back_inserter
14841 #include <memory> // shared_ptr, make_shared
14842 #include <string> // basic_string
14843 #include <vector> // vector
14846 #include <ios> // streamsize
14847 #include <ostream> // basic_ostream
14848 #endif // JSON_NO_IO
14850 // #include <nlohmann/detail/macro_scope.hpp>
14853 NLOHMANN_JSON_NAMESPACE_BEGIN
14857 /// abstract output adapter interface
14858 template<typename CharType> struct output_adapter_protocol
14860 virtual void write_character(CharType c) = 0;
14861 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14862 virtual ~output_adapter_protocol() = default;
14864 output_adapter_protocol() = default;
14865 output_adapter_protocol(const output_adapter_protocol&) = default;
14866 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
14867 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14868 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14871 /// a type to simplify interfaces
14872 template<typename CharType>
14873 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14875 /// output adapter for byte vectors
14876 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14877 class output_vector_adapter : public output_adapter_protocol<CharType>
14880 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14884 void write_character(CharType c) override
14889 JSON_HEDLEY_NON_NULL(2)
14890 void write_characters(const CharType* s, std::size_t length) override
14892 v.insert(v.end(), s, s + length);
14896 std::vector<CharType, AllocatorType>& v;
14900 /// output adapter for output streams
14901 template<typename CharType>
14902 class output_stream_adapter : public output_adapter_protocol<CharType>
14905 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14909 void write_character(CharType c) override
14914 JSON_HEDLEY_NON_NULL(2)
14915 void write_characters(const CharType* s, std::size_t length) override
14917 stream.write(s, static_cast<std::streamsize>(length));
14921 std::basic_ostream<CharType>& stream;
14923 #endif // JSON_NO_IO
14925 /// output adapter for basic_string
14926 template<typename CharType, typename StringType = std::basic_string<CharType>>
14927 class output_string_adapter : public output_adapter_protocol<CharType>
14930 explicit output_string_adapter(StringType& s) noexcept
14934 void write_character(CharType c) override
14939 JSON_HEDLEY_NON_NULL(2)
14940 void write_characters(const CharType* s, std::size_t length) override
14942 str.append(s, length);
14949 template<typename CharType, typename StringType = std::basic_string<CharType>>
14950 class output_adapter
14953 template<typename AllocatorType = std::allocator<CharType>>
14954 output_adapter(std::vector<CharType, AllocatorType>& vec)
14955 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
14958 output_adapter(std::basic_ostream<CharType>& s)
14959 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
14960 #endif // JSON_NO_IO
14962 output_adapter(StringType& s)
14963 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
14965 operator output_adapter_t<CharType>()
14971 output_adapter_t<CharType> oa = nullptr;
14974 } // namespace detail
14975 NLOHMANN_JSON_NAMESPACE_END
14977 // #include <nlohmann/detail/string_concat.hpp>
14980 NLOHMANN_JSON_NAMESPACE_BEGIN
14984 ///////////////////
14985 // binary writer //
14986 ///////////////////
14989 @brief serialization to CBOR and MessagePack values
14991 template<typename BasicJsonType, typename CharType>
14992 class binary_writer
14994 using string_t = typename BasicJsonType::string_t;
14995 using binary_t = typename BasicJsonType::binary_t;
14996 using number_float_t = typename BasicJsonType::number_float_t;
15000 @brief create a binary writer
15002 @param[in] adapter output adapter to write to
15004 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15010 @param[in] j JSON value to serialize
15011 @pre j.type() == value_t::object
15013 void write_bson(const BasicJsonType& j)
15017 case value_t::object:
15019 write_bson_object(*j.m_data.m_value.object);
15023 case value_t::null:
15024 case value_t::array:
15025 case value_t::string:
15026 case value_t::boolean:
15027 case value_t::number_integer:
15028 case value_t::number_unsigned:
15029 case value_t::number_float:
15030 case value_t::binary:
15031 case value_t::discarded:
15034 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15040 @param[in] j JSON value to serialize
15042 void write_cbor(const BasicJsonType& j)
15046 case value_t::null:
15048 oa->write_character(to_char_type(0xF6));
15052 case value_t::boolean:
15054 oa->write_character(j.m_data.m_value.boolean
15055 ? to_char_type(0xF5)
15056 : to_char_type(0xF4));
15060 case value_t::number_integer:
15062 if (j.m_data.m_value.number_integer >= 0)
15064 // CBOR does not differentiate between positive signed
15065 // integers and unsigned integers. Therefore, we used the
15066 // code from the value_t::number_unsigned case here.
15067 if (j.m_data.m_value.number_integer <= 0x17)
15069 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15071 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15073 oa->write_character(to_char_type(0x18));
15074 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15076 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15078 oa->write_character(to_char_type(0x19));
15079 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15081 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15083 oa->write_character(to_char_type(0x1A));
15084 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15088 oa->write_character(to_char_type(0x1B));
15089 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15094 // The conversions below encode the sign in the first
15095 // byte, and the value is converted to a positive number.
15096 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15097 if (j.m_data.m_value.number_integer >= -24)
15099 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15101 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15103 oa->write_character(to_char_type(0x38));
15104 write_number(static_cast<std::uint8_t>(positive_number));
15106 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15108 oa->write_character(to_char_type(0x39));
15109 write_number(static_cast<std::uint16_t>(positive_number));
15111 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15113 oa->write_character(to_char_type(0x3A));
15114 write_number(static_cast<std::uint32_t>(positive_number));
15118 oa->write_character(to_char_type(0x3B));
15119 write_number(static_cast<std::uint64_t>(positive_number));
15125 case value_t::number_unsigned:
15127 if (j.m_data.m_value.number_unsigned <= 0x17)
15129 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15131 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15133 oa->write_character(to_char_type(0x18));
15134 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15136 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15138 oa->write_character(to_char_type(0x19));
15139 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15141 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15143 oa->write_character(to_char_type(0x1A));
15144 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15148 oa->write_character(to_char_type(0x1B));
15149 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15154 case value_t::number_float:
15156 if (std::isnan(j.m_data.m_value.number_float))
15158 // NaN is 0xf97e00 in CBOR
15159 oa->write_character(to_char_type(0xF9));
15160 oa->write_character(to_char_type(0x7E));
15161 oa->write_character(to_char_type(0x00));
15163 else if (std::isinf(j.m_data.m_value.number_float))
15165 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15166 oa->write_character(to_char_type(0xf9));
15167 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15168 oa->write_character(to_char_type(0x00));
15172 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15177 case value_t::string:
15179 // step 1: write control byte and the string length
15180 const auto N = j.m_data.m_value.string->size();
15183 write_number(static_cast<std::uint8_t>(0x60 + N));
15185 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15187 oa->write_character(to_char_type(0x78));
15188 write_number(static_cast<std::uint8_t>(N));
15190 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15192 oa->write_character(to_char_type(0x79));
15193 write_number(static_cast<std::uint16_t>(N));
15195 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15197 oa->write_character(to_char_type(0x7A));
15198 write_number(static_cast<std::uint32_t>(N));
15201 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15203 oa->write_character(to_char_type(0x7B));
15204 write_number(static_cast<std::uint64_t>(N));
15208 // step 2: write the string
15209 oa->write_characters(
15210 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15211 j.m_data.m_value.string->size());
15215 case value_t::array:
15217 // step 1: write control byte and the array size
15218 const auto N = j.m_data.m_value.array->size();
15221 write_number(static_cast<std::uint8_t>(0x80 + N));
15223 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15225 oa->write_character(to_char_type(0x98));
15226 write_number(static_cast<std::uint8_t>(N));
15228 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15230 oa->write_character(to_char_type(0x99));
15231 write_number(static_cast<std::uint16_t>(N));
15233 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15235 oa->write_character(to_char_type(0x9A));
15236 write_number(static_cast<std::uint32_t>(N));
15239 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15241 oa->write_character(to_char_type(0x9B));
15242 write_number(static_cast<std::uint64_t>(N));
15246 // step 2: write each element
15247 for (const auto& el : *j.m_data.m_value.array)
15254 case value_t::binary:
15256 if (j.m_data.m_value.binary->has_subtype())
15258 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15260 write_number(static_cast<std::uint8_t>(0xd8));
15261 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15263 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15265 write_number(static_cast<std::uint8_t>(0xd9));
15266 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15268 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15270 write_number(static_cast<std::uint8_t>(0xda));
15271 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15273 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15275 write_number(static_cast<std::uint8_t>(0xdb));
15276 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15280 // step 1: write control byte and the binary array size
15281 const auto N = j.m_data.m_value.binary->size();
15284 write_number(static_cast<std::uint8_t>(0x40 + N));
15286 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15288 oa->write_character(to_char_type(0x58));
15289 write_number(static_cast<std::uint8_t>(N));
15291 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15293 oa->write_character(to_char_type(0x59));
15294 write_number(static_cast<std::uint16_t>(N));
15296 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15298 oa->write_character(to_char_type(0x5A));
15299 write_number(static_cast<std::uint32_t>(N));
15302 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15304 oa->write_character(to_char_type(0x5B));
15305 write_number(static_cast<std::uint64_t>(N));
15309 // step 2: write each element
15310 oa->write_characters(
15311 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15317 case value_t::object:
15319 // step 1: write control byte and the object size
15320 const auto N = j.m_data.m_value.object->size();
15323 write_number(static_cast<std::uint8_t>(0xA0 + N));
15325 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15327 oa->write_character(to_char_type(0xB8));
15328 write_number(static_cast<std::uint8_t>(N));
15330 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15332 oa->write_character(to_char_type(0xB9));
15333 write_number(static_cast<std::uint16_t>(N));
15335 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15337 oa->write_character(to_char_type(0xBA));
15338 write_number(static_cast<std::uint32_t>(N));
15341 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15343 oa->write_character(to_char_type(0xBB));
15344 write_number(static_cast<std::uint64_t>(N));
15348 // step 2: write each element
15349 for (const auto& el : *j.m_data.m_value.object)
15351 write_cbor(el.first);
15352 write_cbor(el.second);
15357 case value_t::discarded:
15364 @param[in] j JSON value to serialize
15366 void write_msgpack(const BasicJsonType& j)
15370 case value_t::null: // nil
15372 oa->write_character(to_char_type(0xC0));
15376 case value_t::boolean: // true and false
15378 oa->write_character(j.m_data.m_value.boolean
15379 ? to_char_type(0xC3)
15380 : to_char_type(0xC2));
15384 case value_t::number_integer:
15386 if (j.m_data.m_value.number_integer >= 0)
15388 // MessagePack does not differentiate between positive
15389 // signed integers and unsigned integers. Therefore, we used
15390 // the code from the value_t::number_unsigned case here.
15391 if (j.m_data.m_value.number_unsigned < 128)
15394 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15396 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15399 oa->write_character(to_char_type(0xCC));
15400 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15402 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15405 oa->write_character(to_char_type(0xCD));
15406 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15408 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15411 oa->write_character(to_char_type(0xCE));
15412 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15414 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15417 oa->write_character(to_char_type(0xCF));
15418 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15423 if (j.m_data.m_value.number_integer >= -32)
15426 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15428 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15429 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15432 oa->write_character(to_char_type(0xD0));
15433 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15435 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15436 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15439 oa->write_character(to_char_type(0xD1));
15440 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15442 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15443 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15446 oa->write_character(to_char_type(0xD2));
15447 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15449 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15450 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15453 oa->write_character(to_char_type(0xD3));
15454 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15460 case value_t::number_unsigned:
15462 if (j.m_data.m_value.number_unsigned < 128)
15465 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15467 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15470 oa->write_character(to_char_type(0xCC));
15471 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15473 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15476 oa->write_character(to_char_type(0xCD));
15477 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15479 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15482 oa->write_character(to_char_type(0xCE));
15483 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15485 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15488 oa->write_character(to_char_type(0xCF));
15489 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15494 case value_t::number_float:
15496 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15500 case value_t::string:
15502 // step 1: write control byte and the string length
15503 const auto N = j.m_data.m_value.string->size();
15507 write_number(static_cast<std::uint8_t>(0xA0 | N));
15509 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15512 oa->write_character(to_char_type(0xD9));
15513 write_number(static_cast<std::uint8_t>(N));
15515 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15518 oa->write_character(to_char_type(0xDA));
15519 write_number(static_cast<std::uint16_t>(N));
15521 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15524 oa->write_character(to_char_type(0xDB));
15525 write_number(static_cast<std::uint32_t>(N));
15528 // step 2: write the string
15529 oa->write_characters(
15530 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15531 j.m_data.m_value.string->size());
15535 case value_t::array:
15537 // step 1: write control byte and the array size
15538 const auto N = j.m_data.m_value.array->size();
15542 write_number(static_cast<std::uint8_t>(0x90 | N));
15544 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15547 oa->write_character(to_char_type(0xDC));
15548 write_number(static_cast<std::uint16_t>(N));
15550 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15553 oa->write_character(to_char_type(0xDD));
15554 write_number(static_cast<std::uint32_t>(N));
15557 // step 2: write each element
15558 for (const auto& el : *j.m_data.m_value.array)
15565 case value_t::binary:
15567 // step 0: determine if the binary type has a set subtype to
15568 // determine whether or not to use the ext or fixext types
15569 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15571 // step 1: write control byte and the byte string length
15572 const auto N = j.m_data.m_value.binary->size();
15573 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15575 std::uint8_t output_type{};
15582 output_type = 0xD4; // fixext 1
15585 output_type = 0xD5; // fixext 2
15588 output_type = 0xD6; // fixext 4
15591 output_type = 0xD7; // fixext 8
15594 output_type = 0xD8; // fixext 16
15597 output_type = 0xC7; // ext 8
15605 output_type = 0xC4; // bin 8
15609 oa->write_character(to_char_type(output_type));
15612 write_number(static_cast<std::uint8_t>(N));
15615 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15617 const std::uint8_t output_type = use_ext
15621 oa->write_character(to_char_type(output_type));
15622 write_number(static_cast<std::uint16_t>(N));
15624 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15626 const std::uint8_t output_type = use_ext
15630 oa->write_character(to_char_type(output_type));
15631 write_number(static_cast<std::uint32_t>(N));
15634 // step 1.5: if this is an ext type, write the subtype
15637 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15640 // step 2: write the byte string
15641 oa->write_characters(
15642 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15648 case value_t::object:
15650 // step 1: write control byte and the object size
15651 const auto N = j.m_data.m_value.object->size();
15655 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15657 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15660 oa->write_character(to_char_type(0xDE));
15661 write_number(static_cast<std::uint16_t>(N));
15663 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15666 oa->write_character(to_char_type(0xDF));
15667 write_number(static_cast<std::uint32_t>(N));
15670 // step 2: write each element
15671 for (const auto& el : *j.m_data.m_value.object)
15673 write_msgpack(el.first);
15674 write_msgpack(el.second);
15679 case value_t::discarded:
15686 @param[in] j JSON value to serialize
15687 @param[in] use_count whether to use '#' prefixes (optimized format)
15688 @param[in] use_type whether to use '$' prefixes (optimized format)
15689 @param[in] add_prefix whether prefixes need to be used for this value
15690 @param[in] use_bjdata whether write in BJData format, default is false
15692 void write_ubjson(const BasicJsonType& j, const bool use_count,
15693 const bool use_type, const bool add_prefix = true,
15694 const bool use_bjdata = false)
15698 case value_t::null:
15702 oa->write_character(to_char_type('Z'));
15707 case value_t::boolean:
15711 oa->write_character(j.m_data.m_value.boolean
15712 ? to_char_type('T')
15713 : to_char_type('F'));
15718 case value_t::number_integer:
15720 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15724 case value_t::number_unsigned:
15726 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15730 case value_t::number_float:
15732 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15736 case value_t::string:
15740 oa->write_character(to_char_type('S'));
15742 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15743 oa->write_characters(
15744 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15745 j.m_data.m_value.string->size());
15749 case value_t::array:
15753 oa->write_character(to_char_type('['));
15756 bool prefix_required = true;
15757 if (use_type && !j.m_data.m_value.array->empty())
15759 JSON_ASSERT(use_count);
15760 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15761 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15762 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15764 return ubjson_prefix(v, use_bjdata) == first_prefix;
15767 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15769 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15771 prefix_required = false;
15772 oa->write_character(to_char_type('$'));
15773 oa->write_character(first_prefix);
15779 oa->write_character(to_char_type('#'));
15780 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15783 for (const auto& el : *j.m_data.m_value.array)
15785 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15790 oa->write_character(to_char_type(']'));
15796 case value_t::binary:
15800 oa->write_character(to_char_type('['));
15803 if (use_type && !j.m_data.m_value.binary->empty())
15805 JSON_ASSERT(use_count);
15806 oa->write_character(to_char_type('$'));
15807 oa->write_character('U');
15812 oa->write_character(to_char_type('#'));
15813 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15818 oa->write_characters(
15819 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15820 j.m_data.m_value.binary->size());
15824 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15826 oa->write_character(to_char_type('U'));
15827 oa->write_character(j.m_data.m_value.binary->data()[i]);
15833 oa->write_character(to_char_type(']'));
15839 case value_t::object:
15841 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
15843 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15851 oa->write_character(to_char_type('{'));
15854 bool prefix_required = true;
15855 if (use_type && !j.m_data.m_value.object->empty())
15857 JSON_ASSERT(use_count);
15858 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15859 const bool same_prefix = std::all_of(j.begin(), j.end(),
15860 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15862 return ubjson_prefix(v, use_bjdata) == first_prefix;
15865 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15867 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15869 prefix_required = false;
15870 oa->write_character(to_char_type('$'));
15871 oa->write_character(first_prefix);
15877 oa->write_character(to_char_type('#'));
15878 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15881 for (const auto& el : *j.m_data.m_value.object)
15883 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15884 oa->write_characters(
15885 reinterpret_cast<const CharType*>(el.first.c_str()),
15887 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15892 oa->write_character(to_char_type('}'));
15898 case value_t::discarded:
15910 @return The size of a BSON document entry header, including the id marker
15911 and the entry name size (and its null-terminator).
15913 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15915 const auto it = name.find(static_cast<typename string_t::value_type>(0));
15916 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
15918 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
15919 static_cast<void>(j);
15922 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
15926 @brief Writes the given @a element_type and @a name to the output adapter
15928 void write_bson_entry_header(const string_t& name,
15929 const std::uint8_t element_type)
15931 oa->write_character(to_char_type(element_type)); // boolean
15932 oa->write_characters(
15933 reinterpret_cast<const CharType*>(name.c_str()),
15938 @brief Writes a BSON element with key @a name and boolean value @a value
15940 void write_bson_boolean(const string_t& name,
15943 write_bson_entry_header(name, 0x08);
15944 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
15948 @brief Writes a BSON element with key @a name and double value @a value
15950 void write_bson_double(const string_t& name,
15951 const double value)
15953 write_bson_entry_header(name, 0x01);
15954 write_number<double>(value, true);
15958 @return The size of the BSON-encoded string in @a value
15960 static std::size_t calc_bson_string_size(const string_t& value)
15962 return sizeof(std::int32_t) + value.size() + 1ul;
15966 @brief Writes a BSON element with key @a name and string value @a value
15968 void write_bson_string(const string_t& name,
15969 const string_t& value)
15971 write_bson_entry_header(name, 0x02);
15973 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
15974 oa->write_characters(
15975 reinterpret_cast<const CharType*>(value.c_str()),
15980 @brief Writes a BSON element with key @a name and null value
15982 void write_bson_null(const string_t& name)
15984 write_bson_entry_header(name, 0x0A);
15988 @return The size of the BSON-encoded integer @a value
15990 static std::size_t calc_bson_integer_size(const std::int64_t value)
15992 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
15993 ? sizeof(std::int32_t)
15994 : sizeof(std::int64_t);
15998 @brief Writes a BSON element with key @a name and integer @a value
16000 void write_bson_integer(const string_t& name,
16001 const std::int64_t value)
16003 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16005 write_bson_entry_header(name, 0x10); // int32
16006 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16010 write_bson_entry_header(name, 0x12); // int64
16011 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16016 @return The size of the BSON-encoded unsigned integer in @a j
16018 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16020 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16021 ? sizeof(std::int32_t)
16022 : sizeof(std::int64_t);
16026 @brief Writes a BSON element with key @a name and unsigned @a value
16028 void write_bson_unsigned(const string_t& name,
16029 const BasicJsonType& j)
16031 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16033 write_bson_entry_header(name, 0x10 /* int32 */);
16034 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16036 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16038 write_bson_entry_header(name, 0x12 /* int64 */);
16039 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16043 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16048 @brief Writes a BSON element with key @a name and object @a value
16050 void write_bson_object_entry(const string_t& name,
16051 const typename BasicJsonType::object_t& value)
16053 write_bson_entry_header(name, 0x03); // object
16054 write_bson_object(value);
16058 @return The size of the BSON-encoded array @a value
16060 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16062 std::size_t array_index = 0ul;
16064 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16066 return result + calc_bson_element_size(std::to_string(array_index++), el);
16069 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16073 @return The size of the BSON-encoded binary array @a value
16075 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16077 return sizeof(std::int32_t) + value.size() + 1ul;
16081 @brief Writes a BSON element with key @a name and array @a value
16083 void write_bson_array(const string_t& name,
16084 const typename BasicJsonType::array_t& value)
16086 write_bson_entry_header(name, 0x04); // array
16087 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16089 std::size_t array_index = 0ul;
16091 for (const auto& el : value)
16093 write_bson_element(std::to_string(array_index++), el);
16096 oa->write_character(to_char_type(0x00));
16100 @brief Writes a BSON element with key @a name and binary value @a value
16102 void write_bson_binary(const string_t& name,
16103 const binary_t& value)
16105 write_bson_entry_header(name, 0x05);
16107 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16108 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16110 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16114 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16115 @return The calculated size for the BSON document entry for @a j with the given @a name.
16117 static std::size_t calc_bson_element_size(const string_t& name,
16118 const BasicJsonType& j)
16120 const auto header_size = calc_bson_entry_header_size(name, j);
16123 case value_t::object:
16124 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16126 case value_t::array:
16127 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16129 case value_t::binary:
16130 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16132 case value_t::boolean:
16133 return header_size + 1ul;
16135 case value_t::number_float:
16136 return header_size + 8ul;
16138 case value_t::number_integer:
16139 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16141 case value_t::number_unsigned:
16142 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16144 case value_t::string:
16145 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16147 case value_t::null:
16148 return header_size + 0ul;
16151 case value_t::discarded:
16153 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16160 @brief Serializes the JSON value @a j to BSON and associates it with the
16162 @param name The name to associate with the JSON entity @a j within the
16163 current BSON document
16165 void write_bson_element(const string_t& name,
16166 const BasicJsonType& j)
16170 case value_t::object:
16171 return write_bson_object_entry(name, *j.m_data.m_value.object);
16173 case value_t::array:
16174 return write_bson_array(name, *j.m_data.m_value.array);
16176 case value_t::binary:
16177 return write_bson_binary(name, *j.m_data.m_value.binary);
16179 case value_t::boolean:
16180 return write_bson_boolean(name, j.m_data.m_value.boolean);
16182 case value_t::number_float:
16183 return write_bson_double(name, j.m_data.m_value.number_float);
16185 case value_t::number_integer:
16186 return write_bson_integer(name, j.m_data.m_value.number_integer);
16188 case value_t::number_unsigned:
16189 return write_bson_unsigned(name, j);
16191 case value_t::string:
16192 return write_bson_string(name, *j.m_data.m_value.string);
16194 case value_t::null:
16195 return write_bson_null(name);
16198 case value_t::discarded:
16200 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16207 @brief Calculates the size of the BSON serialization of the given
16209 @param[in] value JSON value to serialize
16210 @pre value.type() == value_t::object
16212 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16214 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16215 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16217 return result += calc_bson_element_size(el.first, el.second);
16220 return sizeof(std::int32_t) + document_size + 1ul;
16224 @param[in] value JSON value to serialize
16225 @pre value.type() == value_t::object
16227 void write_bson_object(const typename BasicJsonType::object_t& value)
16229 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16231 for (const auto& el : value)
16233 write_bson_element(el.first, el.second);
16236 oa->write_character(to_char_type(0x00));
16243 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16245 return to_char_type(0xFA); // Single-Precision Float
16248 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16250 return to_char_type(0xFB); // Double-Precision Float
16257 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16259 return to_char_type(0xCA); // float 32
16262 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16264 return to_char_type(0xCB); // float 64
16271 // UBJSON: write number (floating point)
16272 template<typename NumberType, typename std::enable_if<
16273 std::is_floating_point<NumberType>::value, int>::type = 0>
16274 void write_number_with_ubjson_prefix(const NumberType n,
16275 const bool add_prefix,
16276 const bool use_bjdata)
16280 oa->write_character(get_ubjson_float_prefix(n));
16282 write_number(n, use_bjdata);
16285 // UBJSON: write number (unsigned integer)
16286 template<typename NumberType, typename std::enable_if<
16287 std::is_unsigned<NumberType>::value, int>::type = 0>
16288 void write_number_with_ubjson_prefix(const NumberType n,
16289 const bool add_prefix,
16290 const bool use_bjdata)
16292 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16296 oa->write_character(to_char_type('i')); // int8
16298 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16300 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16304 oa->write_character(to_char_type('U')); // uint8
16306 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16308 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16312 oa->write_character(to_char_type('I')); // int16
16314 write_number(static_cast<std::int16_t>(n), use_bjdata);
16316 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16320 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16322 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16324 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16328 oa->write_character(to_char_type('l')); // int32
16330 write_number(static_cast<std::int32_t>(n), use_bjdata);
16332 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16336 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16338 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16340 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16344 oa->write_character(to_char_type('L')); // int64
16346 write_number(static_cast<std::int64_t>(n), use_bjdata);
16348 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16352 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16354 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16360 oa->write_character(to_char_type('H')); // high-precision number
16363 const auto number = BasicJsonType(n).dump();
16364 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16365 for (std::size_t i = 0; i < number.size(); ++i)
16367 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16372 // UBJSON: write number (signed integer)
16373 template < typename NumberType, typename std::enable_if <
16374 std::is_signed<NumberType>::value&&
16375 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16376 void write_number_with_ubjson_prefix(const NumberType n,
16377 const bool add_prefix,
16378 const bool use_bjdata)
16380 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16384 oa->write_character(to_char_type('i')); // int8
16386 write_number(static_cast<std::int8_t>(n), use_bjdata);
16388 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16392 oa->write_character(to_char_type('U')); // uint8
16394 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16396 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16400 oa->write_character(to_char_type('I')); // int16
16402 write_number(static_cast<std::int16_t>(n), use_bjdata);
16404 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16408 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16410 write_number(static_cast<uint16_t>(n), use_bjdata);
16412 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16416 oa->write_character(to_char_type('l')); // int32
16418 write_number(static_cast<std::int32_t>(n), use_bjdata);
16420 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16424 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16426 write_number(static_cast<uint32_t>(n), use_bjdata);
16428 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16432 oa->write_character(to_char_type('L')); // int64
16434 write_number(static_cast<std::int64_t>(n), use_bjdata);
16441 oa->write_character(to_char_type('H')); // high-precision number
16444 const auto number = BasicJsonType(n).dump();
16445 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16446 for (std::size_t i = 0; i < number.size(); ++i)
16448 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16455 @brief determine the type prefix of container values
16457 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16461 case value_t::null:
16464 case value_t::boolean:
16465 return j.m_data.m_value.boolean ? 'T' : 'F';
16467 case value_t::number_integer:
16469 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16473 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16477 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16481 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16485 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16489 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16493 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16497 // anything else is treated as high-precision number
16498 return 'H'; // LCOV_EXCL_LINE
16501 case value_t::number_unsigned:
16503 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16507 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16511 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16515 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16519 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16523 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16527 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16531 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16535 // anything else is treated as high-precision number
16536 return 'H'; // LCOV_EXCL_LINE
16539 case value_t::number_float:
16540 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16542 case value_t::string:
16545 case value_t::array: // fallthrough
16546 case value_t::binary:
16549 case value_t::object:
16552 case value_t::discarded:
16553 default: // discarded values
16558 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16560 return 'd'; // float 32
16563 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16565 return 'D'; // float 64
16569 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
16571 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16573 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16574 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16577 string_t key = "_ArrayType_";
16578 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16579 if (it == bjdtype.end())
16583 CharType dtype = it->second;
16585 key = "_ArraySize_";
16586 std::size_t len = (value.at(key).empty() ? 0 : 1);
16587 for (const auto& el : value.at(key))
16589 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16592 key = "_ArrayData_";
16593 if (value.at(key).size() != len)
16598 oa->write_character('[');
16599 oa->write_character('$');
16600 oa->write_character(dtype);
16601 oa->write_character('#');
16603 key = "_ArraySize_";
16604 write_ubjson(value.at(key), use_count, use_type, true, true);
16606 key = "_ArrayData_";
16607 if (dtype == 'U' || dtype == 'C')
16609 for (const auto& el : value.at(key))
16611 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16614 else if (dtype == 'i')
16616 for (const auto& el : value.at(key))
16618 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16621 else if (dtype == 'u')
16623 for (const auto& el : value.at(key))
16625 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16628 else if (dtype == 'I')
16630 for (const auto& el : value.at(key))
16632 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16635 else if (dtype == 'm')
16637 for (const auto& el : value.at(key))
16639 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16642 else if (dtype == 'l')
16644 for (const auto& el : value.at(key))
16646 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16649 else if (dtype == 'M')
16651 for (const auto& el : value.at(key))
16653 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16656 else if (dtype == 'L')
16658 for (const auto& el : value.at(key))
16660 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16663 else if (dtype == 'd')
16665 for (const auto& el : value.at(key))
16667 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16670 else if (dtype == 'D')
16672 for (const auto& el : value.at(key))
16674 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16680 ///////////////////////
16681 // Utility functions //
16682 ///////////////////////
16685 @brief write a number to output input
16686 @param[in] n number of type @a NumberType
16687 @param[in] OutputIsLittleEndian Set to true if output data is
16688 required to be little endian
16689 @tparam NumberType the type of the number
16691 @note This function needs to respect the system's endianness, because bytes
16692 in CBOR, MessagePack, and UBJSON are stored in network order (big
16693 endian) and therefore need reordering on little endian systems.
16694 On the other hand, BSON and BJData use little endian and should reorder
16695 on big endian systems.
16697 template<typename NumberType>
16698 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16700 // step 1: write number to array of length NumberType
16701 std::array<CharType, sizeof(NumberType)> vec{};
16702 std::memcpy(vec.data(), &n, sizeof(NumberType));
16704 // step 2: write array to output (with possible reordering)
16705 if (is_little_endian != OutputIsLittleEndian)
16707 // reverse byte order prior to conversion if necessary
16708 std::reverse(vec.begin(), vec.end());
16711 oa->write_characters(vec.data(), sizeof(NumberType));
16714 void write_compact_float(const number_float_t n, detail::input_format_t format)
16717 #pragma GCC diagnostic push
16718 #pragma GCC diagnostic ignored "-Wfloat-equal"
16720 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16721 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16722 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16724 oa->write_character(format == detail::input_format_t::cbor
16725 ? get_cbor_float_prefix(static_cast<float>(n))
16726 : get_msgpack_float_prefix(static_cast<float>(n)));
16727 write_number(static_cast<float>(n));
16731 oa->write_character(format == detail::input_format_t::cbor
16732 ? get_cbor_float_prefix(n)
16733 : get_msgpack_float_prefix(n));
16737 #pragma GCC diagnostic pop
16742 // The following to_char_type functions are implement the conversion
16743 // between uint8_t and CharType. In case CharType is not unsigned,
16744 // such a conversion is required to allow values greater than 128.
16745 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16746 template < typename C = CharType,
16747 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16748 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16750 return *reinterpret_cast<char*>(&x);
16753 template < typename C = CharType,
16754 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16755 static CharType to_char_type(std::uint8_t x) noexcept
16757 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16758 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16760 std::memcpy(&result, &x, sizeof(x));
16764 template<typename C = CharType,
16765 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16766 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16771 template < typename InputCharType, typename C = CharType,
16773 std::is_signed<C>::value &&
16774 std::is_signed<char>::value &&
16775 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16777 static constexpr CharType to_char_type(InputCharType x) noexcept
16783 /// whether we can assume little endianness
16784 const bool is_little_endian = little_endianness();
16787 output_adapter_t<CharType> oa = nullptr;
16790 } // namespace detail
16791 NLOHMANN_JSON_NAMESPACE_END
16793 // #include <nlohmann/detail/output/output_adapters.hpp>
16795 // #include <nlohmann/detail/output/serializer.hpp>
16796 // __ _____ _____ _____
16797 // __| | __| | | | JSON for Modern C++
16798 // | | |__ | | | | | | version 3.11.2
16799 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
16801 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16802 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16803 // SPDX-License-Identifier: MIT
16807 #include <algorithm> // reverse, remove, fill, find, none_of
16808 #include <array> // array
16809 #include <clocale> // localeconv, lconv
16810 #include <cmath> // labs, isfinite, isnan, signbit
16811 #include <cstddef> // size_t, ptrdiff_t
16812 #include <cstdint> // uint8_t
16813 #include <cstdio> // snprintf
16814 #include <limits> // numeric_limits
16815 #include <string> // string, char_traits
16816 #include <iomanip> // setfill, setw
16817 #include <type_traits> // is_same
16818 #include <utility> // move
16820 // #include <nlohmann/detail/conversions/to_chars.hpp>
16821 // __ _____ _____ _____
16822 // __| | __| | | | JSON for Modern C++
16823 // | | |__ | | | | | | version 3.11.2
16824 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
16826 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16827 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
16828 // SPDX-License-Identifier: MIT
16832 #include <array> // array
16833 #include <cmath> // signbit, isfinite
16834 #include <cstdint> // intN_t, uintN_t
16835 #include <cstring> // memcpy, memmove
16836 #include <limits> // numeric_limits
16837 #include <type_traits> // conditional
16839 // #include <nlohmann/detail/macro_scope.hpp>
16842 NLOHMANN_JSON_NAMESPACE_BEGIN
16847 @brief implements the Grisu2 algorithm for binary to decimal floating-point
16850 This implementation is a slightly modified version of the reference
16851 implementation which may be obtained from
16852 http://florian.loitsch.com/publications (bench.tar.gz).
16854 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
16856 For a detailed description of the algorithm see:
16858 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
16859 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
16860 Language Design and Implementation, PLDI 2010
16861 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
16862 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
16863 Design and Implementation, PLDI 1996
16865 namespace dtoa_impl
16868 template<typename Target, typename Source>
16869 Target reinterpret_bits(const Source source)
16871 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16874 std::memcpy(&target, &source, sizeof(Source));
16878 struct diyfp // f * 2^e
16880 static constexpr int kPrecision = 64; // = q
16882 std::uint64_t f = 0;
16885 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16888 @brief returns x - y
16889 @pre x.e == y.e and x.f >= y.f
16891 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16893 JSON_ASSERT(x.e == y.e);
16894 JSON_ASSERT(x.f >= y.f);
16896 return {x.f - y.f, x.e};
16900 @brief returns x * y
16901 @note The result is rounded. (Only the upper q bits are returned.)
16903 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16905 static_assert(kPrecision == 64, "internal error");
16908 // f = round((x.f * y.f) / 2^q)
16909 // e = x.e + y.e + q
16911 // Emulate the 64-bit * 64-bit multiplication:
16914 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
16915 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
16916 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
16917 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
16918 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
16919 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
16920 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
16922 // (Since Q might be larger than 2^32 - 1)
16924 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
16926 // (Q_hi + H does not overflow a 64-bit int)
16928 // = p_lo + 2^64 p_hi
16930 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
16931 const std::uint64_t u_hi = x.f >> 32u;
16932 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
16933 const std::uint64_t v_hi = y.f >> 32u;
16935 const std::uint64_t p0 = u_lo * v_lo;
16936 const std::uint64_t p1 = u_lo * v_hi;
16937 const std::uint64_t p2 = u_hi * v_lo;
16938 const std::uint64_t p3 = u_hi * v_hi;
16940 const std::uint64_t p0_hi = p0 >> 32u;
16941 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
16942 const std::uint64_t p1_hi = p1 >> 32u;
16943 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
16944 const std::uint64_t p2_hi = p2 >> 32u;
16946 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
16948 // The full product might now be computed as
16950 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
16951 // p_lo = p0_lo + (Q << 32)
16953 // But in this particular case here, the full p_lo is not required.
16954 // Effectively we only need to add the highest bit in p_lo to p_hi (and
16955 // Q_hi + 1 does not overflow).
16957 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
16959 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
16961 return {h, x.e + y.e + 64};
16965 @brief normalize x such that the significand is >= 2^(q-1)
16968 static diyfp normalize(diyfp x) noexcept
16970 JSON_ASSERT(x.f != 0);
16972 while ((x.f >> 63u) == 0)
16982 @brief normalize x such that the result has the exponent E
16983 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
16985 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
16987 const int delta = x.e - target_exponent;
16989 JSON_ASSERT(delta >= 0);
16990 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
16992 return {x.f << delta, target_exponent};
17004 Compute the (normalized) diyfp representing the input number 'value' and its
17007 @pre value must be finite and positive
17009 template<typename FloatType>
17010 boundaries compute_boundaries(FloatType value)
17012 JSON_ASSERT(std::isfinite(value));
17013 JSON_ASSERT(value > 0);
17015 // Convert the IEEE representation into a diyfp.
17017 // If v is denormal:
17018 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17019 // If v is normalized:
17020 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17022 static_assert(std::numeric_limits<FloatType>::is_iec559,
17023 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17025 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17026 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17027 constexpr int kMinExp = 1 - kBias;
17028 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17030 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17032 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17033 const std::uint64_t E = bits >> (kPrecision - 1);
17034 const std::uint64_t F = bits & (kHiddenBit - 1);
17036 const bool is_denormal = E == 0;
17037 const diyfp v = is_denormal
17038 ? diyfp(F, kMinExp)
17039 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17041 // Compute the boundaries m- and m+ of the floating-point value
17044 // Determine v- and v+, the floating-point predecessor and successor if v,
17047 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17048 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17052 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17053 // between m- and m+ round to v, regardless of how the input rounding
17054 // algorithm breaks ties.
17056 // ---+-------------+-------------+-------------+-------------+--- (A)
17059 // -----------------+------+------+-------------+-------------+--- (B)
17062 const bool lower_boundary_is_closer = F == 0 && E > 1;
17063 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17064 const diyfp m_minus = lower_boundary_is_closer
17065 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17066 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17068 // Determine the normalized w+ = m+.
17069 const diyfp w_plus = diyfp::normalize(m_plus);
17071 // Determine w- = m- such that e_(w-) = e_(w+).
17072 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17074 return {diyfp::normalize(v), w_minus, w_plus};
17077 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
17078 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17079 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
17081 // alpha <= e = e_c + e_w + q <= gamma
17085 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17086 // <= f_c * f_w * 2^gamma
17088 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17090 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17094 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17096 // The choice of (alpha,gamma) determines the size of the table and the form of
17097 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17100 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
17101 // processed independently: An integral part p1, and a fractional part p2:
17103 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17104 // = (f div 2^-e) + (f mod 2^-e) * 2^e
17107 // The conversion of p1 into decimal form requires a series of divisions and
17108 // modulos by (a power of) 10. These operations are faster for 32-bit than for
17109 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17110 // achieved by choosing
17112 // -e >= 32 or e <= -32 := gamma
17114 // In order to convert the fractional part
17116 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17118 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17119 // d[-i] are extracted in order:
17121 // (10 * p2) div 2^-e = d[-1]
17122 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17124 // The multiplication by 10 must not overflow. It is sufficient to choose
17126 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17128 // Since p2 = f mod 2^-e < 2^-e,
17130 // -e <= 60 or e >= -60 := alpha
17132 constexpr int kAlpha = -60;
17133 constexpr int kGamma = -32;
17135 struct cached_power // c = f * 2^e ~= 10^k
17143 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
17144 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
17145 satisfies (Definition 3.2 from [1])
17147 alpha <= e_c + e + q <= gamma.
17149 inline cached_power get_cached_power_for_binary_exponent(int e)
17153 // alpha <= e_c + e + q <= gamma (1)
17154 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17156 // and since the c's are normalized, 2^(q-1) <= f_c,
17158 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17159 // ==> 2^(alpha - e - 1) <= c
17161 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17163 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17164 // = ceil( (alpha - e - 1) * log_10(2) )
17167 // "In theory the result of the procedure could be wrong since c is rounded,
17168 // and the computation itself is approximated [...]. In practice, however,
17169 // this simple function is sufficient."
17171 // For IEEE double precision floating-point numbers converted into
17172 // normalized diyfp's w = f * 2^e, with q = 64,
17174 // e >= -1022 (min IEEE exponent)
17176 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17177 // -11 (normalize the diyfp)
17182 // e <= +1023 (max IEEE exponent)
17184 // -11 (normalize the diyfp)
17187 // This binary exponent range [-1137,960] results in a decimal exponent
17188 // range [-307,324]. One does not need to store a cached power for each
17189 // k in this range. For each such k it suffices to find a cached power
17190 // such that the exponent of the product lies in [alpha,gamma].
17191 // This implies that the difference of the decimal exponents of adjacent
17192 // table entries must be less than or equal to
17194 // floor( (gamma - alpha) * log_10(2) ) = 8.
17196 // (A smaller distance gamma-alpha would require a larger table.)
17199 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17201 constexpr int kCachedPowersMinDecExp = -300;
17202 constexpr int kCachedPowersDecStep = 8;
17204 static constexpr std::array<cached_power, 79> kCachedPowers =
17207 { 0xAB70FE17C79AC6CA, -1060, -300 },
17208 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17209 { 0xBE5691EF416BD60C, -1007, -284 },
17210 { 0x8DD01FAD907FFC3C, -980, -276 },
17211 { 0xD3515C2831559A83, -954, -268 },
17212 { 0x9D71AC8FADA6C9B5, -927, -260 },
17213 { 0xEA9C227723EE8BCB, -901, -252 },
17214 { 0xAECC49914078536D, -874, -244 },
17215 { 0x823C12795DB6CE57, -847, -236 },
17216 { 0xC21094364DFB5637, -821, -228 },
17217 { 0x9096EA6F3848984F, -794, -220 },
17218 { 0xD77485CB25823AC7, -768, -212 },
17219 { 0xA086CFCD97BF97F4, -741, -204 },
17220 { 0xEF340A98172AACE5, -715, -196 },
17221 { 0xB23867FB2A35B28E, -688, -188 },
17222 { 0x84C8D4DFD2C63F3B, -661, -180 },
17223 { 0xC5DD44271AD3CDBA, -635, -172 },
17224 { 0x936B9FCEBB25C996, -608, -164 },
17225 { 0xDBAC6C247D62A584, -582, -156 },
17226 { 0xA3AB66580D5FDAF6, -555, -148 },
17227 { 0xF3E2F893DEC3F126, -529, -140 },
17228 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17229 { 0x87625F056C7C4A8B, -475, -124 },
17230 { 0xC9BCFF6034C13053, -449, -116 },
17231 { 0x964E858C91BA2655, -422, -108 },
17232 { 0xDFF9772470297EBD, -396, -100 },
17233 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17234 { 0xF8A95FCF88747D94, -343, -84 },
17235 { 0xB94470938FA89BCF, -316, -76 },
17236 { 0x8A08F0F8BF0F156B, -289, -68 },
17237 { 0xCDB02555653131B6, -263, -60 },
17238 { 0x993FE2C6D07B7FAC, -236, -52 },
17239 { 0xE45C10C42A2B3B06, -210, -44 },
17240 { 0xAA242499697392D3, -183, -36 },
17241 { 0xFD87B5F28300CA0E, -157, -28 },
17242 { 0xBCE5086492111AEB, -130, -20 },
17243 { 0x8CBCCC096F5088CC, -103, -12 },
17244 { 0xD1B71758E219652C, -77, -4 },
17245 { 0x9C40000000000000, -50, 4 },
17246 { 0xE8D4A51000000000, -24, 12 },
17247 { 0xAD78EBC5AC620000, 3, 20 },
17248 { 0x813F3978F8940984, 30, 28 },
17249 { 0xC097CE7BC90715B3, 56, 36 },
17250 { 0x8F7E32CE7BEA5C70, 83, 44 },
17251 { 0xD5D238A4ABE98068, 109, 52 },
17252 { 0x9F4F2726179A2245, 136, 60 },
17253 { 0xED63A231D4C4FB27, 162, 68 },
17254 { 0xB0DE65388CC8ADA8, 189, 76 },
17255 { 0x83C7088E1AAB65DB, 216, 84 },
17256 { 0xC45D1DF942711D9A, 242, 92 },
17257 { 0x924D692CA61BE758, 269, 100 },
17258 { 0xDA01EE641A708DEA, 295, 108 },
17259 { 0xA26DA3999AEF774A, 322, 116 },
17260 { 0xF209787BB47D6B85, 348, 124 },
17261 { 0xB454E4A179DD1877, 375, 132 },
17262 { 0x865B86925B9BC5C2, 402, 140 },
17263 { 0xC83553C5C8965D3D, 428, 148 },
17264 { 0x952AB45CFA97A0B3, 455, 156 },
17265 { 0xDE469FBD99A05FE3, 481, 164 },
17266 { 0xA59BC234DB398C25, 508, 172 },
17267 { 0xF6C69A72A3989F5C, 534, 180 },
17268 { 0xB7DCBF5354E9BECE, 561, 188 },
17269 { 0x88FCF317F22241E2, 588, 196 },
17270 { 0xCC20CE9BD35C78A5, 614, 204 },
17271 { 0x98165AF37B2153DF, 641, 212 },
17272 { 0xE2A0B5DC971F303A, 667, 220 },
17273 { 0xA8D9D1535CE3B396, 694, 228 },
17274 { 0xFB9B7CD9A4A7443C, 720, 236 },
17275 { 0xBB764C4CA7A44410, 747, 244 },
17276 { 0x8BAB8EEFB6409C1A, 774, 252 },
17277 { 0xD01FEF10A657842C, 800, 260 },
17278 { 0x9B10A4E5E9913129, 827, 268 },
17279 { 0xE7109BFBA19C0C9D, 853, 276 },
17280 { 0xAC2820D9623BF429, 880, 284 },
17281 { 0x80444B5E7AA7CF85, 907, 292 },
17282 { 0xBF21E44003ACDD2D, 933, 300 },
17283 { 0x8E679C2F5E44FF8F, 960, 308 },
17284 { 0xD433179D9C8CB841, 986, 316 },
17285 { 0x9E19DB92B4E31BA9, 1013, 324 },
17289 // This computation gives exactly the same results for k as
17290 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17291 // for |e| <= 1500, but doesn't require floating-point operations.
17292 // NB: log_10(2) ~= 78913 / 2^18
17293 JSON_ASSERT(e >= -1500);
17294 JSON_ASSERT(e <= 1500);
17295 const int f = kAlpha - e - 1;
17296 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17298 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17299 JSON_ASSERT(index >= 0);
17300 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17302 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17303 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17304 JSON_ASSERT(kGamma >= cached.e + e + 64);
17310 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
17311 For n == 0, returns 1 and sets pow10 := 1.
17313 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17316 if (n >= 1000000000)
17318 pow10 = 1000000000;
17322 if (n >= 100000000)
17367 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17368 std::uint64_t rest, std::uint64_t ten_k)
17370 JSON_ASSERT(len >= 1);
17371 JSON_ASSERT(dist <= delta);
17372 JSON_ASSERT(rest <= delta);
17373 JSON_ASSERT(ten_k > 0);
17375 // <--------------------------- delta ---->
17376 // <---- dist --------->
17377 // --------------[------------------+-------------------]--------------
17382 // <---- rest ---->
17383 // --------------[------------------+----+--------------]--------------
17387 // ten_k represents a unit-in-the-last-place in the decimal representation
17389 // Decrement buf by ten_k while this takes buf closer to w.
17391 // The tests are written in this order to avoid overflow in unsigned
17392 // integer arithmetic.
17395 && delta - rest >= ten_k
17396 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17398 JSON_ASSERT(buf[len - 1] != '0');
17405 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
17406 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
17408 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17409 diyfp M_minus, diyfp w, diyfp M_plus)
17411 static_assert(kAlpha >= -60, "internal error");
17412 static_assert(kGamma <= -32, "internal error");
17414 // Generates the digits (and the exponent) of a decimal floating-point
17415 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17416 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17418 // <--------------------------- delta ---->
17419 // <---- dist --------->
17420 // --------------[------------------+-------------------]--------------
17423 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17424 // V is in [M-,M+].
17426 JSON_ASSERT(M_plus.e >= kAlpha);
17427 JSON_ASSERT(M_plus.e <= kGamma);
17429 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17430 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17432 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17435 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17436 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17439 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17441 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17442 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17446 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17448 JSON_ASSERT(p1 > 0);
17450 std::uint32_t pow10{};
17451 const int k = find_largest_pow10(p1, pow10);
17453 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17455 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17456 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17458 // M+ = p1 + p2 * 2^e
17459 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17460 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17461 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17463 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17465 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17467 // but stop as soon as
17469 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17475 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17476 // pow10 = 10^(n-1) <= p1 < 10^n
17478 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17479 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17481 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17482 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17484 JSON_ASSERT(d <= 9);
17485 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17487 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17492 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17496 // Now check if enough digits have been generated.
17499 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17502 // Since rest and delta share the same exponent e, it suffices to
17503 // compare the significands.
17504 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17507 // V = buffer * 10^n, with M- <= V <= M+.
17509 decimal_exponent += n;
17511 // We may now just stop. But instead look if the buffer could be
17512 // decremented to bring V closer to w.
17514 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17515 // The rounding procedure works with diyfp's with an implicit
17518 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17520 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17521 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17528 // pow10 = 10^(n-1) <= p1 < 10^n
17529 // Invariants restored.
17534 // The digits of the integral part have been generated:
17536 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17537 // = buffer + p2 * 2^e
17539 // Now generate the digits of the fractional part p2 * 2^e.
17542 // No decimal point is generated: the exponent is adjusted instead.
17544 // p2 actually represents the fraction
17548 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17550 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17552 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17553 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17557 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17558 // = ( d) * 2^-e + ( r)
17561 // 10^m * p2 * 2^e = d + r * 2^e
17565 // M+ = buffer + p2 * 2^e
17566 // = buffer + 10^-m * (d + r * 2^e)
17567 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17569 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17571 JSON_ASSERT(p2 > delta);
17577 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17578 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17579 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17580 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17582 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17584 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17585 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17587 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17588 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17589 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17591 JSON_ASSERT(d <= 9);
17592 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17594 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17599 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17600 // Invariant restored.
17602 // Check if enough digits have been generated.
17604 // 10^-m * p2 * 2^e <= delta * 2^e
17605 // p2 * 2^e <= 10^m * delta * 2^e
17606 // p2 <= 10^m * delta
17615 // V = buffer * 10^-m, with M- <= V <= M+.
17617 decimal_exponent -= m;
17619 // 1 ulp in the decimal representation is now 10^-m.
17620 // Since delta and dist are now scaled by 10^m, we need to do the
17621 // same with ulp in order to keep the units in sync.
17623 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17625 const std::uint64_t ten_m = one.f;
17626 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17628 // By construction this algorithm generates the shortest possible decimal
17629 // number (Loitsch, Theorem 6.2) which rounds back to w.
17630 // For an input number of precision p, at least
17632 // N = 1 + ceil(p * log_10(2))
17634 // decimal digits are sufficient to identify all binary floating-point
17635 // numbers (Matula, "In-and-Out conversions").
17636 // This implies that the algorithm does not produce more than N decimal
17639 // N = 17 for p = 53 (IEEE double precision)
17640 // N = 9 for p = 24 (IEEE single precision)
17644 v = buf * 10^decimal_exponent
17645 len is the length of the buffer (number of decimal digits)
17646 The buffer must be large enough, i.e. >= max_digits10.
17648 JSON_HEDLEY_NON_NULL(1)
17649 inline void grisu2(char* buf, int& len, int& decimal_exponent,
17650 diyfp m_minus, diyfp v, diyfp m_plus)
17652 JSON_ASSERT(m_plus.e == m_minus.e);
17653 JSON_ASSERT(m_plus.e == v.e);
17655 // --------(-----------------------+-----------------------)-------- (A)
17658 // --------------------(-----------+-----------------------)-------- (B)
17661 // First scale v (and m- and m+) such that the exponent is in the range
17664 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17666 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17668 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17669 const diyfp w = diyfp::mul(v, c_minus_k);
17670 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17671 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17673 // ----(---+---)---------------(---+---)---------------(---+---)----
17675 // = c*m- = c*v = c*m+
17677 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17678 // w+ are now off by a small amount.
17681 // w - v * 10^k < 1 ulp
17683 // To account for this inaccuracy, add resp. subtract 1 ulp.
17685 // --------+---[---------------(---+---)---------------]---+--------
17688 // Now any number in [M-, M+] (bounds included) will round to w when input,
17689 // regardless of how the input rounding algorithm breaks ties.
17691 // And digit_gen generates the shortest possible such number in [M-, M+].
17692 // Note that this does not mean that Grisu2 always generates the shortest
17693 // possible number in the interval (m-, m+).
17694 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17695 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17697 decimal_exponent = -cached.k; // = -(-k) = k
17699 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17703 v = buf * 10^decimal_exponent
17704 len is the length of the buffer (number of decimal digits)
17705 The buffer must be large enough, i.e. >= max_digits10.
17707 template<typename FloatType>
17708 JSON_HEDLEY_NON_NULL(1)
17709 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17711 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17712 "internal error: not enough precision");
17714 JSON_ASSERT(std::isfinite(value));
17715 JSON_ASSERT(value > 0);
17717 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17718 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17719 // decimal representations are not exactly "short".
17721 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17722 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17723 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17725 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17726 // representation using the corresponding std::from_chars function recovers value exactly". That
17727 // indicates that single precision floating-point numbers should be recovered using
17730 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17731 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17732 // value is off by 1 ulp.
17733 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17734 const boundaries w = compute_boundaries(static_cast<double>(value));
17736 const boundaries w = compute_boundaries(value);
17739 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17743 @brief appends a decimal representation of e to buf
17744 @return a pointer to the element following the exponent.
17745 @pre -1000 < e < 1000
17747 JSON_HEDLEY_NON_NULL(1)
17748 JSON_HEDLEY_RETURNS_NON_NULL
17749 inline char* append_exponent(char* buf, int e)
17751 JSON_ASSERT(e > -1000);
17752 JSON_ASSERT(e < 1000);
17764 auto k = static_cast<std::uint32_t>(e);
17767 // Always print at least two digits in the exponent.
17768 // This is for compatibility with printf("%g").
17770 *buf++ = static_cast<char>('0' + k);
17774 *buf++ = static_cast<char>('0' + k / 10);
17776 *buf++ = static_cast<char>('0' + k);
17780 *buf++ = static_cast<char>('0' + k / 100);
17782 *buf++ = static_cast<char>('0' + k / 10);
17784 *buf++ = static_cast<char>('0' + k);
17791 @brief prettify v = buf * 10^decimal_exponent
17793 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
17794 notation. Otherwise it will be printed in exponential notation.
17799 JSON_HEDLEY_NON_NULL(1)
17800 JSON_HEDLEY_RETURNS_NON_NULL
17801 inline char* format_buffer(char* buf, int len, int decimal_exponent,
17802 int min_exp, int max_exp)
17804 JSON_ASSERT(min_exp < 0);
17805 JSON_ASSERT(max_exp > 0);
17808 const int n = len + decimal_exponent;
17810 // v = buf * 10^(n-k)
17811 // k is the length of the buffer (number of decimal digits)
17812 // n is the position of the decimal point relative to the start of the buffer.
17814 if (k <= n && n <= max_exp)
17817 // len <= max_exp + 2
17819 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17820 // Make it look like a floating-point number (#362, #378)
17823 return buf + (static_cast<size_t>(n) + 2);
17826 if (0 < n && n <= max_exp)
17829 // len <= max_digits10 + 1
17831 JSON_ASSERT(k > n);
17833 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17835 return buf + (static_cast<size_t>(k) + 1U);
17838 if (min_exp < n && n <= 0)
17841 // len <= 2 + (-min_exp - 1) + max_digits10
17843 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17846 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17847 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17860 // len <= max_digits10 + 1 + 5
17862 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17864 buf += 1 + static_cast<size_t>(k);
17868 return append_exponent(buf, n - 1);
17871 } // namespace dtoa_impl
17874 @brief generates a decimal representation of the floating-point number value in [first, last).
17876 The format of the resulting decimal representation is similar to printf's %g
17877 format. Returns an iterator pointing past-the-end of the decimal representation.
17879 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
17880 @note The buffer must be large enough.
17881 @note The result is NOT null-terminated.
17883 template<typename FloatType>
17884 JSON_HEDLEY_NON_NULL(1, 2)
17885 JSON_HEDLEY_RETURNS_NON_NULL
17886 char* to_chars(char* first, const char* last, FloatType value)
17888 static_cast<void>(last); // maybe unused - fix warning
17889 JSON_ASSERT(std::isfinite(value));
17891 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17892 if (std::signbit(value))
17899 #pragma GCC diagnostic push
17900 #pragma GCC diagnostic ignored "-Wfloat-equal"
17902 if (value == 0) // +-0
17905 // Make it look like a floating-point number (#362, #378)
17911 #pragma GCC diagnostic pop
17914 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
17916 // Compute v = buffer * 10^decimal_exponent.
17917 // The decimal digits are stored in the buffer, which needs to be interpreted
17918 // as an unsigned decimal integer.
17919 // len is the length of the buffer, i.e. the number of decimal digits.
17921 int decimal_exponent = 0;
17922 dtoa_impl::grisu2(first, len, decimal_exponent, value);
17924 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
17926 // Format the buffer like printf("%.*g", prec, value)
17927 constexpr int kMinExp = -4;
17928 // Use digits10 here to increase compatibility with version 2.
17929 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
17931 JSON_ASSERT(last - first >= kMaxExp + 2);
17932 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
17933 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
17935 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
17938 } // namespace detail
17939 NLOHMANN_JSON_NAMESPACE_END
17941 // #include <nlohmann/detail/exceptions.hpp>
17943 // #include <nlohmann/detail/macro_scope.hpp>
17945 // #include <nlohmann/detail/meta/cpp_future.hpp>
17947 // #include <nlohmann/detail/output/binary_writer.hpp>
17949 // #include <nlohmann/detail/output/output_adapters.hpp>
17951 // #include <nlohmann/detail/string_concat.hpp>
17953 // #include <nlohmann/detail/value_t.hpp>
17956 NLOHMANN_JSON_NAMESPACE_BEGIN
17960 ///////////////////
17961 // serialization //
17962 ///////////////////
17964 /// how to treat decoding errors
17965 enum class error_handler_t
17967 strict, ///< throw a type_error exception in case of invalid UTF-8
17968 replace, ///< replace invalid UTF-8 sequences with U+FFFD
17969 ignore ///< ignore invalid UTF-8 sequences
17972 template<typename BasicJsonType>
17975 using string_t = typename BasicJsonType::string_t;
17976 using number_float_t = typename BasicJsonType::number_float_t;
17977 using number_integer_t = typename BasicJsonType::number_integer_t;
17978 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
17979 using binary_char_t = typename BasicJsonType::binary_t::value_type;
17980 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17981 static constexpr std::uint8_t UTF8_REJECT = 1;
17985 @param[in] s output stream to serialize to
17986 @param[in] ichar indentation character to use
17987 @param[in] error_handler_ how to react on decoding errors
17989 serializer(output_adapter_t<char> s, const char ichar,
17990 error_handler_t error_handler_ = error_handler_t::strict)
17992 , loc(std::localeconv())
17993 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
17994 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
17995 , indent_char(ichar)
17996 , indent_string(512, indent_char)
17997 , error_handler(error_handler_)
18000 // delete because of pointer members
18001 serializer(const serializer&) = delete;
18002 serializer& operator=(const serializer&) = delete;
18003 serializer(serializer&&) = delete;
18004 serializer& operator=(serializer&&) = delete;
18005 ~serializer() = default;
18008 @brief internal implementation of the serialization function
18010 This function is called by the public member function dump and organizes
18011 the serialization internally. The indentation level is propagated as
18012 additional parameter. In case of arrays and objects, the function is
18013 called recursively.
18015 - strings and object keys are escaped using `escape_string()`
18016 - integer numbers are converted implicitly via `operator<<`
18017 - floating-point numbers are converted to a string using `"%g"` format
18018 - binary values are serialized as objects containing the subtype and the
18021 @param[in] val value to serialize
18022 @param[in] pretty_print whether the output shall be pretty-printed
18023 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18024 in the output are escaped with `\uXXXX` sequences, and the result consists
18025 of ASCII characters only.
18026 @param[in] indent_step the indent level
18027 @param[in] current_indent the current indent level (only used internally)
18029 void dump(const BasicJsonType& val,
18030 const bool pretty_print,
18031 const bool ensure_ascii,
18032 const unsigned int indent_step,
18033 const unsigned int current_indent = 0)
18035 switch (val.m_data.m_type)
18037 case value_t::object:
18039 if (val.m_data.m_value.object->empty())
18041 o->write_characters("{}", 2);
18047 o->write_characters("{\n", 2);
18049 // variable to hold indentation for recursive calls
18050 const auto new_indent = current_indent + indent_step;
18051 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18053 indent_string.resize(indent_string.size() * 2, ' ');
18056 // first n-1 elements
18057 auto i = val.m_data.m_value.object->cbegin();
18058 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18060 o->write_characters(indent_string.c_str(), new_indent);
18061 o->write_character('\"');
18062 dump_escaped(i->first, ensure_ascii);
18063 o->write_characters("\": ", 3);
18064 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18065 o->write_characters(",\n", 2);
18069 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18070 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18071 o->write_characters(indent_string.c_str(), new_indent);
18072 o->write_character('\"');
18073 dump_escaped(i->first, ensure_ascii);
18074 o->write_characters("\": ", 3);
18075 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18077 o->write_character('\n');
18078 o->write_characters(indent_string.c_str(), current_indent);
18079 o->write_character('}');
18083 o->write_character('{');
18085 // first n-1 elements
18086 auto i = val.m_data.m_value.object->cbegin();
18087 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18089 o->write_character('\"');
18090 dump_escaped(i->first, ensure_ascii);
18091 o->write_characters("\":", 2);
18092 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18093 o->write_character(',');
18097 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18098 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18099 o->write_character('\"');
18100 dump_escaped(i->first, ensure_ascii);
18101 o->write_characters("\":", 2);
18102 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18104 o->write_character('}');
18110 case value_t::array:
18112 if (val.m_data.m_value.array->empty())
18114 o->write_characters("[]", 2);
18120 o->write_characters("[\n", 2);
18122 // variable to hold indentation for recursive calls
18123 const auto new_indent = current_indent + indent_step;
18124 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18126 indent_string.resize(indent_string.size() * 2, ' ');
18129 // first n-1 elements
18130 for (auto i = val.m_data.m_value.array->cbegin();
18131 i != val.m_data.m_value.array->cend() - 1; ++i)
18133 o->write_characters(indent_string.c_str(), new_indent);
18134 dump(*i, true, ensure_ascii, indent_step, new_indent);
18135 o->write_characters(",\n", 2);
18139 JSON_ASSERT(!val.m_data.m_value.array->empty());
18140 o->write_characters(indent_string.c_str(), new_indent);
18141 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18143 o->write_character('\n');
18144 o->write_characters(indent_string.c_str(), current_indent);
18145 o->write_character(']');
18149 o->write_character('[');
18151 // first n-1 elements
18152 for (auto i = val.m_data.m_value.array->cbegin();
18153 i != val.m_data.m_value.array->cend() - 1; ++i)
18155 dump(*i, false, ensure_ascii, indent_step, current_indent);
18156 o->write_character(',');
18160 JSON_ASSERT(!val.m_data.m_value.array->empty());
18161 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18163 o->write_character(']');
18169 case value_t::string:
18171 o->write_character('\"');
18172 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18173 o->write_character('\"');
18177 case value_t::binary:
18181 o->write_characters("{\n", 2);
18183 // variable to hold indentation for recursive calls
18184 const auto new_indent = current_indent + indent_step;
18185 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18187 indent_string.resize(indent_string.size() * 2, ' ');
18190 o->write_characters(indent_string.c_str(), new_indent);
18192 o->write_characters("\"bytes\": [", 10);
18194 if (!val.m_data.m_value.binary->empty())
18196 for (auto i = val.m_data.m_value.binary->cbegin();
18197 i != val.m_data.m_value.binary->cend() - 1; ++i)
18200 o->write_characters(", ", 2);
18202 dump_integer(val.m_data.m_value.binary->back());
18205 o->write_characters("],\n", 3);
18206 o->write_characters(indent_string.c_str(), new_indent);
18208 o->write_characters("\"subtype\": ", 11);
18209 if (val.m_data.m_value.binary->has_subtype())
18211 dump_integer(val.m_data.m_value.binary->subtype());
18215 o->write_characters("null", 4);
18217 o->write_character('\n');
18218 o->write_characters(indent_string.c_str(), current_indent);
18219 o->write_character('}');
18223 o->write_characters("{\"bytes\":[", 10);
18225 if (!val.m_data.m_value.binary->empty())
18227 for (auto i = val.m_data.m_value.binary->cbegin();
18228 i != val.m_data.m_value.binary->cend() - 1; ++i)
18231 o->write_character(',');
18233 dump_integer(val.m_data.m_value.binary->back());
18236 o->write_characters("],\"subtype\":", 12);
18237 if (val.m_data.m_value.binary->has_subtype())
18239 dump_integer(val.m_data.m_value.binary->subtype());
18240 o->write_character('}');
18244 o->write_characters("null}", 5);
18250 case value_t::boolean:
18252 if (val.m_data.m_value.boolean)
18254 o->write_characters("true", 4);
18258 o->write_characters("false", 5);
18263 case value_t::number_integer:
18265 dump_integer(val.m_data.m_value.number_integer);
18269 case value_t::number_unsigned:
18271 dump_integer(val.m_data.m_value.number_unsigned);
18275 case value_t::number_float:
18277 dump_float(val.m_data.m_value.number_float);
18281 case value_t::discarded:
18283 o->write_characters("<discarded>", 11);
18287 case value_t::null:
18289 o->write_characters("null", 4);
18293 default: // LCOV_EXCL_LINE
18294 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18298 JSON_PRIVATE_UNLESS_TESTED:
18300 @brief dump escaped string
18302 Escape a string by replacing certain special characters by a sequence of an
18303 escape character (backslash) and another character and other control
18304 characters by a sequence of "\u" followed by a four-digit hex
18305 representation. The escaped string is written to output stream @a o.
18307 @param[in] s the string to escape
18308 @param[in] ensure_ascii whether to escape non-ASCII characters with
18311 @complexity Linear in the length of string @a s.
18313 void dump_escaped(const string_t& s, const bool ensure_ascii)
18315 std::uint32_t codepoint{};
18316 std::uint8_t state = UTF8_ACCEPT;
18317 std::size_t bytes = 0; // number of bytes written to string_buffer
18319 // number of bytes written at the point of the last valid byte
18320 std::size_t bytes_after_last_accept = 0;
18321 std::size_t undumped_chars = 0;
18323 for (std::size_t i = 0; i < s.size(); ++i)
18325 const auto byte = static_cast<std::uint8_t>(s[i]);
18327 switch (decode(state, codepoint, byte))
18329 case UTF8_ACCEPT: // decode found a new code point
18333 case 0x08: // backspace
18335 string_buffer[bytes++] = '\\';
18336 string_buffer[bytes++] = 'b';
18340 case 0x09: // horizontal tab
18342 string_buffer[bytes++] = '\\';
18343 string_buffer[bytes++] = 't';
18347 case 0x0A: // newline
18349 string_buffer[bytes++] = '\\';
18350 string_buffer[bytes++] = 'n';
18354 case 0x0C: // formfeed
18356 string_buffer[bytes++] = '\\';
18357 string_buffer[bytes++] = 'f';
18361 case 0x0D: // carriage return
18363 string_buffer[bytes++] = '\\';
18364 string_buffer[bytes++] = 'r';
18368 case 0x22: // quotation mark
18370 string_buffer[bytes++] = '\\';
18371 string_buffer[bytes++] = '\"';
18375 case 0x5C: // reverse solidus
18377 string_buffer[bytes++] = '\\';
18378 string_buffer[bytes++] = '\\';
18384 // escape control characters (0x00..0x1F) or, if
18385 // ensure_ascii parameter is used, non-ASCII characters
18386 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18388 if (codepoint <= 0xFFFF)
18390 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18391 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18392 static_cast<std::uint16_t>(codepoint)));
18397 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18398 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18399 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18400 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18406 // copy byte to buffer (all previous bytes
18407 // been copied have in default case above)
18408 string_buffer[bytes++] = s[i];
18414 // write buffer and reset index; there must be 13 bytes
18415 // left, as this is the maximal number of bytes to be
18416 // written ("\uxxxx\uxxxx\0") for one code point
18417 if (string_buffer.size() - bytes < 13)
18419 o->write_characters(string_buffer.data(), bytes);
18423 // remember the byte position of this accept
18424 bytes_after_last_accept = bytes;
18425 undumped_chars = 0;
18429 case UTF8_REJECT: // decode found invalid UTF-8 byte
18431 switch (error_handler)
18433 case error_handler_t::strict:
18435 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18438 case error_handler_t::ignore:
18439 case error_handler_t::replace:
18441 // in case we saw this character the first time, we
18442 // would like to read it again, because the byte
18443 // may be OK for itself, but just not OK for the
18444 // previous sequence
18445 if (undumped_chars > 0)
18450 // reset length buffer to the last accepted index;
18451 // thus removing/ignoring the invalid characters
18452 bytes = bytes_after_last_accept;
18454 if (error_handler == error_handler_t::replace)
18456 // add a replacement character
18459 string_buffer[bytes++] = '\\';
18460 string_buffer[bytes++] = 'u';
18461 string_buffer[bytes++] = 'f';
18462 string_buffer[bytes++] = 'f';
18463 string_buffer[bytes++] = 'f';
18464 string_buffer[bytes++] = 'd';
18468 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18469 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18470 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18473 // write buffer and reset index; there must be 13 bytes
18474 // left, as this is the maximal number of bytes to be
18475 // written ("\uxxxx\uxxxx\0") for one code point
18476 if (string_buffer.size() - bytes < 13)
18478 o->write_characters(string_buffer.data(), bytes);
18482 bytes_after_last_accept = bytes;
18485 undumped_chars = 0;
18487 // continue processing the string
18488 state = UTF8_ACCEPT;
18492 default: // LCOV_EXCL_LINE
18493 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18498 default: // decode found yet incomplete multi-byte code point
18502 // code point will not be escaped - copy byte to buffer
18503 string_buffer[bytes++] = s[i];
18511 // we finished processing the string
18512 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18517 o->write_characters(string_buffer.data(), bytes);
18522 // we finish reading, but do not accept: string was incomplete
18523 switch (error_handler)
18525 case error_handler_t::strict:
18527 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18530 case error_handler_t::ignore:
18532 // write all accepted bytes
18533 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18537 case error_handler_t::replace:
18539 // write all accepted bytes
18540 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18541 // add a replacement character
18544 o->write_characters("\\ufffd", 6);
18548 o->write_characters("\xEF\xBF\xBD", 3);
18553 default: // LCOV_EXCL_LINE
18554 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18561 @brief count digits
18563 Count the number of decimal (base 10) digits for an input unsigned integer.
18565 @param[in] x unsigned integer number to count its digits
18566 @return number of decimal digits
18568 inline unsigned int count_digits(number_unsigned_t x) noexcept
18570 unsigned int n_digits = 1;
18579 return n_digits + 1;
18583 return n_digits + 2;
18587 return n_digits + 3;
18595 * @brief convert a byte to a uppercase hex representation
18596 * @param[in] byte byte to represent
18597 * @return representation ("00".."FF")
18599 static std::string hex_bytes(std::uint8_t byte)
18601 std::string result = "FF";
18602 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18603 result[0] = nibble_to_hex[byte / 16];
18604 result[1] = nibble_to_hex[byte % 16];
18608 // templates to avoid warnings about useless casts
18609 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18610 bool is_negative_number(NumberType x)
18615 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18616 bool is_negative_number(NumberType /*unused*/)
18622 @brief dump an integer
18624 Dump a given integer to output stream @a o. Works internally with
18627 @param[in] x integer number (signed or unsigned) to dump
18628 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
18630 template < typename NumberType, detail::enable_if_t <
18631 std::is_integral<NumberType>::value ||
18632 std::is_same<NumberType, number_unsigned_t>::value ||
18633 std::is_same<NumberType, number_integer_t>::value ||
18634 std::is_same<NumberType, binary_char_t>::value,
18636 void dump_integer(NumberType x)
18638 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18641 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18642 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18643 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18644 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18645 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18646 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18647 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18648 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18649 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18650 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18654 // special case for "0"
18657 o->write_character('0');
18661 // use a pointer to fill the buffer
18662 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18664 number_unsigned_t abs_value;
18666 unsigned int n_chars{};
18668 if (is_negative_number(x))
18671 abs_value = remove_sign(static_cast<number_integer_t>(x));
18673 // account one more byte for the minus sign
18674 n_chars = 1 + count_digits(abs_value);
18678 abs_value = static_cast<number_unsigned_t>(x);
18679 n_chars = count_digits(abs_value);
18682 // spare 1 byte for '\0'
18683 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18685 // jump to the end to generate the string from backward,
18686 // so we later avoid reversing the result
18687 buffer_ptr += n_chars;
18689 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18690 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18691 while (abs_value >= 100)
18693 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18695 *(--buffer_ptr) = digits_to_99[digits_index][1];
18696 *(--buffer_ptr) = digits_to_99[digits_index][0];
18699 if (abs_value >= 10)
18701 const auto digits_index = static_cast<unsigned>(abs_value);
18702 *(--buffer_ptr) = digits_to_99[digits_index][1];
18703 *(--buffer_ptr) = digits_to_99[digits_index][0];
18707 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18710 o->write_characters(number_buffer.data(), n_chars);
18714 @brief dump a floating-point number
18716 Dump a given floating-point number to output stream @a o. Works internally
18717 with @a number_buffer.
18719 @param[in] x floating-point number to dump
18721 void dump_float(number_float_t x)
18724 if (!std::isfinite(x))
18726 o->write_characters("null", 4);
18730 // If number_float_t is an IEEE-754 single or double precision number,
18731 // use the Grisu2 algorithm to produce short numbers which are
18732 // guaranteed to round-trip, using strtof and strtod, resp.
18734 // NB: The test below works if <long double> == <double>.
18735 static constexpr bool is_ieee_single_or_double
18736 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18737 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18739 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18742 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18744 auto* begin = number_buffer.data();
18745 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18747 o->write_characters(begin, static_cast<size_t>(end - begin));
18750 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18752 // get number of digits for a float -> text -> float round-trip
18753 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18755 // the actual conversion
18756 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18757 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18759 // negative value indicates an error
18760 JSON_ASSERT(len > 0);
18761 // check if buffer was large enough
18762 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18764 // erase thousands separator
18765 if (thousands_sep != '\0')
18767 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18768 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18769 std::fill(end, number_buffer.end(), '\0');
18770 JSON_ASSERT((end - number_buffer.begin()) <= len);
18771 len = (end - number_buffer.begin());
18774 // convert decimal point to '.'
18775 if (decimal_point != '\0' && decimal_point != '.')
18777 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18778 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18779 if (dec_pos != number_buffer.end())
18785 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18787 // determine if we need to append ".0"
18788 const bool value_is_int_like =
18789 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18792 return c == '.' || c == 'e';
18795 if (value_is_int_like)
18797 o->write_characters(".0", 2);
18802 @brief check whether a string is UTF-8 encoded
18804 The function checks each byte of a string whether it is UTF-8 encoded. The
18805 result of the check is stored in the @a state parameter. The function must
18806 be called initially with state 0 (accept). State 1 means the string must
18807 be rejected, because the current byte is not allowed. If the string is
18808 completely processed, but the state is non-zero, the string ended
18809 prematurely; that is, the last byte indicated more bytes should have
18812 @param[in,out] state the state of the decoding
18813 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
18814 @param[in] byte next byte to decode
18817 @note The function has been edited: a std::array is used.
18819 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
18820 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
18822 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18824 static const std::array<std::uint8_t, 400> utf8d =
18827 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
18828 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
18829 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
18830 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
18831 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
18832 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
18833 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
18834 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18835 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18836 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18837 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
18838 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
18839 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
18840 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
18844 JSON_ASSERT(byte < utf8d.size());
18845 const std::uint8_t type = utf8d[byte];
18847 codep = (state != UTF8_ACCEPT)
18848 ? (byte & 0x3fu) | (codep << 6u)
18849 : (0xFFu >> type) & (byte);
18851 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18852 JSON_ASSERT(index < utf8d.size());
18853 state = utf8d[index];
18858 * Overload to make the compiler happy while it is instantiating
18859 * dump_integer for number_unsigned_t.
18860 * Must never be called.
18862 number_unsigned_t remove_sign(number_unsigned_t x)
18864 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18865 return x; // LCOV_EXCL_LINE
18869 * Helper function for dump_integer
18871 * This function takes a negative signed integer and returns its absolute
18872 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18873 * not directly remove the sign of an arbitrary signed integer as the
18874 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18875 * #1708 for details.
18877 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18879 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18880 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18884 /// the output of the serializer
18885 output_adapter_t<char> o = nullptr;
18887 /// a (hopefully) large enough character buffer
18888 std::array<char, 64> number_buffer{{}};
18891 const std::lconv* loc = nullptr;
18892 /// the locale's thousand separator character
18893 const char thousands_sep = '\0';
18894 /// the locale's decimal point character
18895 const char decimal_point = '\0';
18898 std::array<char, 512> string_buffer{{}};
18900 /// the indentation character
18901 const char indent_char;
18902 /// the indentation string
18903 string_t indent_string;
18905 /// error_handler how to react on decoding errors
18906 const error_handler_t error_handler;
18909 } // namespace detail
18910 NLOHMANN_JSON_NAMESPACE_END
18912 // #include <nlohmann/detail/value_t.hpp>
18914 // #include <nlohmann/json_fwd.hpp>
18916 // #include <nlohmann/ordered_map.hpp>
18917 // __ _____ _____ _____
18918 // __| | __| | | | JSON for Modern C++
18919 // | | |__ | | | | | | version 3.11.2
18920 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
18922 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
18923 // SPDX-License-Identifier: MIT
18927 #include <functional> // equal_to, less
18928 #include <initializer_list> // initializer_list
18929 #include <iterator> // input_iterator_tag, iterator_traits
18930 #include <memory> // allocator
18931 #include <stdexcept> // for out_of_range
18932 #include <type_traits> // enable_if, is_convertible
18933 #include <utility> // pair
18934 #include <vector> // vector
18936 // #include <nlohmann/detail/macro_scope.hpp>
18938 // #include <nlohmann/detail/meta/type_traits.hpp>
18941 NLOHMANN_JSON_NAMESPACE_BEGIN
18943 /// ordered_map: a minimal map-like container that preserves insertion order
18944 /// for use within nlohmann::basic_json<ordered_map>
18945 template <class Key, class T, class IgnoredLess = std::less<Key>,
18946 class Allocator = std::allocator<std::pair<const Key, T>>>
18947 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
18949 using key_type = Key;
18950 using mapped_type = T;
18951 using Container = std::vector<std::pair<const Key, T>, Allocator>;
18952 using iterator = typename Container::iterator;
18953 using const_iterator = typename Container::const_iterator;
18954 using size_type = typename Container::size_type;
18955 using value_type = typename Container::value_type;
18956 #ifdef JSON_HAS_CPP_14
18957 using key_compare = std::equal_to<>;
18959 using key_compare = std::equal_to<Key>;
18962 // Explicit constructors instead of `using Container::Container`
18963 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
18964 ordered_map() noexcept(noexcept(Container())) : Container{} {}
18965 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
18966 template <class It>
18967 ordered_map(It first, It last, const Allocator& alloc = Allocator())
18968 : Container{first, last, alloc} {}
18969 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
18970 : Container{init, alloc} {}
18972 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
18974 for (auto it = this->begin(); it != this->end(); ++it)
18976 if (m_compare(it->first, key))
18978 return {it, false};
18981 Container::emplace_back(key, std::forward<T>(t));
18982 return {std::prev(this->end()), true};
18985 template<class KeyType, detail::enable_if_t<
18986 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
18987 std::pair<iterator, bool> emplace(KeyType && key, T && t)
18989 for (auto it = this->begin(); it != this->end(); ++it)
18991 if (m_compare(it->first, key))
18993 return {it, false};
18996 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
18997 return {std::prev(this->end()), true};
19000 T& operator[](const key_type& key)
19002 return emplace(key, T{}).first->second;
19005 template<class KeyType, detail::enable_if_t<
19006 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19007 T & operator[](KeyType && key)
19009 return emplace(std::forward<KeyType>(key), T{}).first->second;
19012 const T& operator[](const key_type& key) const
19017 template<class KeyType, detail::enable_if_t<
19018 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19019 const T & operator[](KeyType && key) const
19021 return at(std::forward<KeyType>(key));
19024 T& at(const key_type& key)
19026 for (auto it = this->begin(); it != this->end(); ++it)
19028 if (m_compare(it->first, key))
19034 JSON_THROW(std::out_of_range("key not found"));
19037 template<class KeyType, detail::enable_if_t<
19038 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19039 T & at(KeyType && key)
19041 for (auto it = this->begin(); it != this->end(); ++it)
19043 if (m_compare(it->first, key))
19049 JSON_THROW(std::out_of_range("key not found"));
19052 const T& at(const key_type& key) const
19054 for (auto it = this->begin(); it != this->end(); ++it)
19056 if (m_compare(it->first, key))
19062 JSON_THROW(std::out_of_range("key not found"));
19065 template<class KeyType, detail::enable_if_t<
19066 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19067 const T & at(KeyType && key) const
19069 for (auto it = this->begin(); it != this->end(); ++it)
19071 if (m_compare(it->first, key))
19077 JSON_THROW(std::out_of_range("key not found"));
19080 size_type erase(const key_type& key)
19082 for (auto it = this->begin(); it != this->end(); ++it)
19084 if (m_compare(it->first, key))
19086 // Since we cannot move const Keys, re-construct them in place
19087 for (auto next = it; ++next != this->end(); ++it)
19089 it->~value_type(); // Destroy but keep allocation
19090 new (&*it) value_type{std::move(*next)};
19092 Container::pop_back();
19099 template<class KeyType, detail::enable_if_t<
19100 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19101 size_type erase(KeyType && key)
19103 for (auto it = this->begin(); it != this->end(); ++it)
19105 if (m_compare(it->first, key))
19107 // Since we cannot move const Keys, re-construct them in place
19108 for (auto next = it; ++next != this->end(); ++it)
19110 it->~value_type(); // Destroy but keep allocation
19111 new (&*it) value_type{std::move(*next)};
19113 Container::pop_back();
19120 iterator erase(iterator pos)
19122 return erase(pos, std::next(pos));
19125 iterator erase(iterator first, iterator last)
19132 const auto elements_affected = std::distance(first, last);
19133 const auto offset = std::distance(Container::begin(), first);
19135 // This is the start situation. We need to delete elements_affected
19136 // elements (3 in this example: e, f, g), and need to return an
19137 // iterator past the last deleted element (h in this example).
19138 // Note that offset is the distance from the start of the vector
19139 // to first. We will need this later.
19141 // [ a, b, c, d, e, f, g, h, i, j ]
19145 // Since we cannot move const Keys, we re-construct them in place.
19146 // We start at first and re-construct (viz. copy) the elements from
19147 // the back of the vector. Example for first iteration:
19150 // v | destroy e and re-construct with h
19151 // [ a, b, c, d, e, f, g, h, i, j ]
19153 // it it + elements_affected
19155 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19157 it->~value_type(); // destroy but keep allocation
19158 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19161 // [ a, b, c, d, h, i, j, h, i, j ]
19165 // remove the unneeded elements at the end of the vector
19166 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19168 // [ a, b, c, d, h, i, j ]
19172 // first is now pointing past the last deleted element, but we cannot
19173 // use this iterator, because it may have been invalidated by the
19174 // resize call. Instead, we can return begin() + offset.
19175 return Container::begin() + offset;
19178 size_type count(const key_type& key) const
19180 for (auto it = this->begin(); it != this->end(); ++it)
19182 if (m_compare(it->first, key))
19190 template<class KeyType, detail::enable_if_t<
19191 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19192 size_type count(KeyType && key) const
19194 for (auto it = this->begin(); it != this->end(); ++it)
19196 if (m_compare(it->first, key))
19204 iterator find(const key_type& key)
19206 for (auto it = this->begin(); it != this->end(); ++it)
19208 if (m_compare(it->first, key))
19213 return Container::end();
19216 template<class KeyType, detail::enable_if_t<
19217 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19218 iterator find(KeyType && key)
19220 for (auto it = this->begin(); it != this->end(); ++it)
19222 if (m_compare(it->first, key))
19227 return Container::end();
19230 const_iterator find(const key_type& key) const
19232 for (auto it = this->begin(); it != this->end(); ++it)
19234 if (m_compare(it->first, key))
19239 return Container::end();
19242 std::pair<iterator, bool> insert( value_type&& value )
19244 return emplace(value.first, std::move(value.second));
19247 std::pair<iterator, bool> insert( const value_type& value )
19249 for (auto it = this->begin(); it != this->end(); ++it)
19251 if (m_compare(it->first, value.first))
19253 return {it, false};
19256 Container::push_back(value);
19257 return {--this->end(), true};
19260 template<typename InputIt>
19261 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19262 std::input_iterator_tag>::value>::type;
19264 template<typename InputIt, typename = require_input_iter<InputIt>>
19265 void insert(InputIt first, InputIt last)
19267 for (auto it = first; it != last; ++it)
19274 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19277 NLOHMANN_JSON_NAMESPACE_END
19280 #if defined(JSON_HAS_CPP_17)
19282 #include <string_view>
19286 @brief namespace for Niels Lohmann
19287 @see https://github.com/nlohmann
19288 @since version 1.0.0
19290 NLOHMANN_JSON_NAMESPACE_BEGIN
19293 @brief a class to store JSON values
19296 @invariant The member variables @a m_value and @a m_type have the following
19298 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
19299 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
19300 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
19301 The invariants are checked by member function assert_invariant().
19303 @note ObjectType trick from https://stackoverflow.com/a/9860911
19306 @since version 1.0.0
19310 NLOHMANN_BASIC_JSON_TPL_DECLARATION
19311 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19312 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19315 template<detail::value_t> friend struct detail::external_constructor;
19318 friend class ::nlohmann::json_pointer;
19319 // can be restored when json_pointer backwards compatibility is removed
19320 // friend ::nlohmann::json_pointer<StringType>;
19322 template<typename BasicJsonType, typename InputType>
19323 friend class ::nlohmann::detail::parser;
19324 friend ::nlohmann::detail::serializer<basic_json>;
19325 template<typename BasicJsonType>
19326 friend class ::nlohmann::detail::iter_impl;
19327 template<typename BasicJsonType, typename CharType>
19328 friend class ::nlohmann::detail::binary_writer;
19329 template<typename BasicJsonType, typename InputType, typename SAX>
19330 friend class ::nlohmann::detail::binary_reader;
19331 template<typename BasicJsonType>
19332 friend class ::nlohmann::detail::json_sax_dom_parser;
19333 template<typename BasicJsonType>
19334 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19335 friend class ::nlohmann::detail::exception;
19337 /// workaround type for MSVC
19338 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19339 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19341 JSON_PRIVATE_UNLESS_TESTED:
19342 // convenience aliases for types residing in namespace detail;
19343 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19345 template<typename InputAdapterType>
19346 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19347 InputAdapterType adapter,
19348 detail::parser_callback_t<basic_json>cb = nullptr,
19349 const bool allow_exceptions = true,
19350 const bool ignore_comments = false
19353 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19354 std::move(cb), allow_exceptions, ignore_comments);
19358 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19359 template<typename BasicJsonType>
19360 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19361 template<typename BasicJsonType>
19362 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19363 template<typename Iterator>
19364 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19365 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19367 template<typename CharType>
19368 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19370 template<typename InputType>
19371 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19372 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19374 JSON_PRIVATE_UNLESS_TESTED:
19375 using serializer = ::nlohmann::detail::serializer<basic_json>;
19378 using value_t = detail::value_t;
19379 /// JSON Pointer, see @ref nlohmann::json_pointer
19380 using json_pointer = ::nlohmann::json_pointer<StringType>;
19381 template<typename T, typename SFINAE>
19382 using json_serializer = JSONSerializer<T, SFINAE>;
19383 /// how to treat decoding errors
19384 using error_handler_t = detail::error_handler_t;
19385 /// how to treat CBOR tags
19386 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
19387 /// helper type for initializer lists of basic_json values
19388 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19390 using input_format_t = detail::input_format_t;
19391 /// SAX interface type, see @ref nlohmann::json_sax
19392 using json_sax_t = json_sax<basic_json>;
19398 /// @name exceptions
19399 /// Classes to implement user-defined exceptions.
19402 using exception = detail::exception;
19403 using parse_error = detail::parse_error;
19404 using invalid_iterator = detail::invalid_iterator;
19405 using type_error = detail::type_error;
19406 using out_of_range = detail::out_of_range;
19407 using other_error = detail::other_error;
19412 /////////////////////
19413 // container types //
19414 /////////////////////
19416 /// @name container types
19417 /// The canonic container types to use @ref basic_json like any other STL
19421 /// the type of elements in a basic_json container
19422 using value_type = basic_json;
19424 /// the type of an element reference
19425 using reference = value_type&;
19426 /// the type of an element const reference
19427 using const_reference = const value_type&;
19429 /// a type to represent differences between iterators
19430 using difference_type = std::ptrdiff_t;
19431 /// a type to represent container sizes
19432 using size_type = std::size_t;
19434 /// the allocator type
19435 using allocator_type = AllocatorType<basic_json>;
19437 /// the type of an element pointer
19438 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19439 /// the type of an element const pointer
19440 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19442 /// an iterator for a basic_json container
19443 using iterator = iter_impl<basic_json>;
19444 /// a const iterator for a basic_json container
19445 using const_iterator = iter_impl<const basic_json>;
19446 /// a reverse iterator for a basic_json container
19447 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19448 /// a const reverse iterator for a basic_json container
19449 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19454 /// @brief returns the allocator associated with the container
19455 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
19456 static allocator_type get_allocator()
19458 return allocator_type();
19461 /// @brief returns version information on the library
19462 /// @sa https://json.nlohmann.me/api/basic_json/meta/
19463 JSON_HEDLEY_WARN_UNUSED_RESULT
19464 static basic_json meta()
19468 result["copyright"] = "(C) 2013-2022 Niels Lohmann";
19469 result["name"] = "JSON for Modern C++";
19470 result["url"] = "https://github.com/nlohmann/json";
19471 result["version"]["string"] =
19472 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19473 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19474 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19475 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19476 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19477 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19480 result["platform"] = "win32";
19481 #elif defined __linux__
19482 result["platform"] = "linux";
19483 #elif defined __APPLE__
19484 result["platform"] = "apple";
19485 #elif defined __unix__
19486 result["platform"] = "unix";
19488 result["platform"] = "unknown";
19491 #if defined(__ICC) || defined(__INTEL_COMPILER)
19492 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19493 #elif defined(__clang__)
19494 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19495 #elif defined(__GNUC__) || defined(__GNUG__)
19496 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19497 std::to_string(__GNUC__), '.',
19498 std::to_string(__GNUC_MINOR__), '.',
19499 std::to_string(__GNUC_PATCHLEVEL__))
19502 #elif defined(__HP_cc) || defined(__HP_aCC)
19503 result["compiler"] = "hp"
19504 #elif defined(__IBMCPP__)
19505 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19506 #elif defined(_MSC_VER)
19507 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19508 #elif defined(__PGI)
19509 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19510 #elif defined(__SUNPRO_CC)
19511 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19513 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19517 #if defined(_MSVC_LANG)
19518 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19519 #elif defined(__cplusplus)
19520 result["compiler"]["c++"] = std::to_string(__cplusplus);
19522 result["compiler"]["c++"] = "unknown";
19528 ///////////////////////////
19529 // JSON value data types //
19530 ///////////////////////////
19532 /// @name JSON value data types
19533 /// The data types to store a JSON value. These types are derived from
19534 /// the template arguments passed to class @ref basic_json.
19537 /// @brief default object key comparator type
19538 /// The actual object key comparator type (@ref object_comparator_t) may be
19540 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
19541 #if defined(JSON_HAS_CPP_14)
19542 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19543 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19544 using default_object_comparator_t = std::less<>;
19546 using default_object_comparator_t = std::less<StringType>;
19549 /// @brief a type for an object
19550 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
19551 using object_t = ObjectType<StringType,
19553 default_object_comparator_t,
19554 AllocatorType<std::pair<const StringType,
19557 /// @brief a type for an array
19558 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
19559 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19561 /// @brief a type for a string
19562 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
19563 using string_t = StringType;
19565 /// @brief a type for a boolean
19566 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
19567 using boolean_t = BooleanType;
19569 /// @brief a type for a number (integer)
19570 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
19571 using number_integer_t = NumberIntegerType;
19573 /// @brief a type for a number (unsigned)
19574 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
19575 using number_unsigned_t = NumberUnsignedType;
19577 /// @brief a type for a number (floating-point)
19578 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
19579 using number_float_t = NumberFloatType;
19581 /// @brief a type for a packed binary type
19582 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
19583 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19585 /// @brief object key comparator type
19586 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
19587 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19593 /// helper for exception-safe object creation
19594 template<typename T, typename... Args>
19595 JSON_HEDLEY_RETURNS_NON_NULL
19596 static T* create(Args&& ... args)
19598 AllocatorType<T> alloc;
19599 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19601 auto deleter = [&](T * obj)
19603 AllocatorTraits::deallocate(alloc, obj, 1);
19605 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19606 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19607 JSON_ASSERT(obj != nullptr);
19608 return obj.release();
19611 ////////////////////////
19612 // JSON value storage //
19613 ////////////////////////
19615 JSON_PRIVATE_UNLESS_TESTED:
19617 @brief a JSON value
19619 The actual storage for a JSON value of the @ref basic_json class. This
19620 union combines the different storage types for the JSON value types
19621 defined in @ref value_t.
19623 JSON type | value_t type | used type
19624 --------- | --------------- | ------------------------
19625 object | object | pointer to @ref object_t
19626 array | array | pointer to @ref array_t
19627 string | string | pointer to @ref string_t
19628 boolean | boolean | @ref boolean_t
19629 number | number_integer | @ref number_integer_t
19630 number | number_unsigned | @ref number_unsigned_t
19631 number | number_float | @ref number_float_t
19632 binary | binary | pointer to @ref binary_t
19633 null | null | *no value is stored*
19635 @note Variable-length types (objects, arrays, and strings) are stored as
19636 pointers. The size of the union should not exceed 64 bits if the default
19637 value types are used.
19639 @since version 1.0.0
19643 /// object (stored with pointer to save storage)
19645 /// array (stored with pointer to save storage)
19647 /// string (stored with pointer to save storage)
19649 /// binary (stored with pointer to save storage)
19653 /// number (integer)
19654 number_integer_t number_integer;
19655 /// number (unsigned integer)
19656 number_unsigned_t number_unsigned;
19657 /// number (floating-point)
19658 number_float_t number_float;
19660 /// default constructor (for null values)
19661 json_value() = default;
19662 /// constructor for booleans
19663 json_value(boolean_t v) noexcept : boolean(v) {}
19664 /// constructor for numbers (integer)
19665 json_value(number_integer_t v) noexcept : number_integer(v) {}
19666 /// constructor for numbers (unsigned)
19667 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19668 /// constructor for numbers (floating-point)
19669 json_value(number_float_t v) noexcept : number_float(v) {}
19670 /// constructor for empty values of a given type
19671 json_value(value_t t)
19675 case value_t::object:
19677 object = create<object_t>();
19681 case value_t::array:
19683 array = create<array_t>();
19687 case value_t::string:
19689 string = create<string_t>("");
19693 case value_t::binary:
19695 binary = create<binary_t>();
19699 case value_t::boolean:
19701 boolean = static_cast<boolean_t>(false);
19705 case value_t::number_integer:
19707 number_integer = static_cast<number_integer_t>(0);
19711 case value_t::number_unsigned:
19713 number_unsigned = static_cast<number_unsigned_t>(0);
19717 case value_t::number_float:
19719 number_float = static_cast<number_float_t>(0.0);
19723 case value_t::null:
19725 object = nullptr; // silence warning, see #821
19729 case value_t::discarded:
19732 object = nullptr; // silence warning, see #821
19733 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19735 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
19742 /// constructor for strings
19743 json_value(const string_t& value) : string(create<string_t>(value)) {}
19745 /// constructor for rvalue strings
19746 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19748 /// constructor for objects
19749 json_value(const object_t& value) : object(create<object_t>(value)) {}
19751 /// constructor for rvalue objects
19752 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19754 /// constructor for arrays
19755 json_value(const array_t& value) : array(create<array_t>(value)) {}
19757 /// constructor for rvalue arrays
19758 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19760 /// constructor for binary arrays
19761 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19763 /// constructor for rvalue binary arrays
19764 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19766 /// constructor for binary arrays (internal type)
19767 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19769 /// constructor for rvalue binary arrays (internal type)
19770 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19772 void destroy(value_t t)
19775 (t == value_t::object && object == nullptr) ||
19776 (t == value_t::array && array == nullptr) ||
19777 (t == value_t::string && string == nullptr) ||
19778 (t == value_t::binary && binary == nullptr)
19781 //not initialized (e.g. due to exception in the ctor)
19784 if (t == value_t::array || t == value_t::object)
19786 // flatten the current json_value to a heap-allocated stack
19787 std::vector<basic_json> stack;
19789 // move the top-level items to stack
19790 if (t == value_t::array)
19792 stack.reserve(array->size());
19793 std::move(array->begin(), array->end(), std::back_inserter(stack));
19797 stack.reserve(object->size());
19798 for (auto&& it : *object)
19800 stack.push_back(std::move(it.second));
19804 while (!stack.empty())
19806 // move the last item to local variable to be processed
19807 basic_json current_item(std::move(stack.back()));
19810 // if current_item is array/object, move
19811 // its children to the stack to be processed later
19812 if (current_item.is_array())
19814 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19816 current_item.m_data.m_value.array->clear();
19818 else if (current_item.is_object())
19820 for (auto&& it : *current_item.m_data.m_value.object)
19822 stack.push_back(std::move(it.second));
19825 current_item.m_data.m_value.object->clear();
19828 // it's now safe that current_item get destructed
19829 // since it doesn't have any children
19835 case value_t::object:
19837 AllocatorType<object_t> alloc;
19838 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19839 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19843 case value_t::array:
19845 AllocatorType<array_t> alloc;
19846 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19847 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19851 case value_t::string:
19853 AllocatorType<string_t> alloc;
19854 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19855 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19859 case value_t::binary:
19861 AllocatorType<binary_t> alloc;
19862 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19863 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19867 case value_t::null:
19868 case value_t::boolean:
19869 case value_t::number_integer:
19870 case value_t::number_unsigned:
19871 case value_t::number_float:
19872 case value_t::discarded:
19883 @brief checks the class invariants
19885 This function asserts the class invariants. It needs to be called at the
19886 end of every constructor to make sure that created objects respect the
19887 invariant. Furthermore, it has to be called each time the type of a JSON
19888 value is changed, because the invariant expresses a relationship between
19889 @a m_type and @a m_value.
19891 Furthermore, the parent relation is checked for arrays and objects: If
19892 @a check_parents true and the value is an array or object, then the
19893 container's elements must have the current value as parent.
19895 @param[in] check_parents whether the parent relation should be checked.
19896 The value is true by default and should only be set to false
19897 during destruction of objects when the invariant does not
19900 void assert_invariant(bool check_parents = true) const noexcept
19902 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19903 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19904 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19905 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19907 #if JSON_DIAGNOSTICS
19910 // cppcheck-suppress assertWithSideEffect
19911 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
19913 return j.m_parent == this;
19916 JSON_CATCH(...) {} // LCOV_EXCL_LINE
19918 static_cast<void>(check_parents);
19923 #if JSON_DIAGNOSTICS
19924 switch (m_data.m_type)
19926 case value_t::array:
19928 for (auto& element : *m_data.m_value.array)
19930 element.m_parent = this;
19935 case value_t::object:
19937 for (auto& element : *m_data.m_value.object)
19939 element.second.m_parent = this;
19944 case value_t::null:
19945 case value_t::string:
19946 case value_t::boolean:
19947 case value_t::number_integer:
19948 case value_t::number_unsigned:
19949 case value_t::number_float:
19950 case value_t::binary:
19951 case value_t::discarded:
19958 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
19960 #if JSON_DIAGNOSTICS
19961 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
19963 (it + i)->m_parent = this;
19966 static_cast<void>(count_set_parents);
19971 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
19973 #if JSON_DIAGNOSTICS
19974 if (old_capacity != static_cast<std::size_t>(-1))
19976 // see https://github.com/nlohmann/json/issues/2838
19977 JSON_ASSERT(type() == value_t::array);
19978 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
19980 // capacity has changed: update all parents
19986 // ordered_json uses a vector internally, so pointers could have
19987 // been invalidated; see https://github.com/nlohmann/json/issues/2962
19988 #ifdef JSON_HEDLEY_MSVC_VERSION
19989 #pragma warning(push )
19990 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
19992 if (detail::is_ordered_map<object_t>::value)
19997 #ifdef JSON_HEDLEY_MSVC_VERSION
19998 #pragma warning( pop )
20003 static_cast<void>(j);
20004 static_cast<void>(old_capacity);
20010 //////////////////////////
20011 // JSON parser callback //
20012 //////////////////////////
20014 /// @brief parser event types
20015 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20016 using parse_event_t = detail::parse_event_t;
20018 /// @brief per-element parser callback type
20019 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20020 using parser_callback_t = detail::parser_callback_t<basic_json>;
20026 /// @name constructors and destructors
20027 /// Constructors of class @ref basic_json, copy/move constructor, copy
20028 /// assignment, static functions creating objects, and the destructor.
20031 /// @brief create an empty value with a given type
20032 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20033 basic_json(const value_t v)
20036 assert_invariant();
20039 /// @brief create a null object
20040 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20041 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20042 : basic_json(value_t::null)
20044 assert_invariant();
20047 /// @brief create a JSON value from compatible types
20048 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20049 template < typename CompatibleType,
20050 typename U = detail::uncvref_t<CompatibleType>,
20051 detail::enable_if_t <
20052 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20053 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20054 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20055 std::forward<CompatibleType>(val))))
20057 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20059 assert_invariant();
20062 /// @brief create a JSON value from an existing one
20063 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20064 template < typename BasicJsonType,
20065 detail::enable_if_t <
20066 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20067 basic_json(const BasicJsonType& val)
20069 using other_boolean_t = typename BasicJsonType::boolean_t;
20070 using other_number_float_t = typename BasicJsonType::number_float_t;
20071 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20072 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20073 using other_string_t = typename BasicJsonType::string_t;
20074 using other_object_t = typename BasicJsonType::object_t;
20075 using other_array_t = typename BasicJsonType::array_t;
20076 using other_binary_t = typename BasicJsonType::binary_t;
20078 switch (val.type())
20080 case value_t::boolean:
20081 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20083 case value_t::number_float:
20084 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20086 case value_t::number_integer:
20087 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20089 case value_t::number_unsigned:
20090 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20092 case value_t::string:
20093 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20095 case value_t::object:
20096 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20098 case value_t::array:
20099 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20101 case value_t::binary:
20102 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20104 case value_t::null:
20107 case value_t::discarded:
20108 m_data.m_type = value_t::discarded;
20110 default: // LCOV_EXCL_LINE
20111 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20113 JSON_ASSERT(m_data.m_type == val.type());
20115 assert_invariant();
20118 /// @brief create a container (array or object) from an initializer list
20119 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20120 basic_json(initializer_list_t init,
20121 bool type_deduction = true,
20122 value_t manual_type = value_t::array)
20124 // check if each element is an array with two elements whose first
20125 // element is a string
20126 bool is_an_object = std::all_of(init.begin(), init.end(),
20127 [](const detail::json_ref<basic_json>& element_ref)
20129 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
20132 // adjust type if type deduction is not wanted
20133 if (!type_deduction)
20135 // if array is wanted, do not create an object though possible
20136 if (manual_type == value_t::array)
20138 is_an_object = false;
20141 // if object is wanted but impossible, throw an exception
20142 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20144 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20150 // the initializer list is a list of pairs -> create object
20151 m_data.m_type = value_t::object;
20152 m_data.m_value = value_t::object;
20154 for (auto& element_ref : init)
20156 auto element = element_ref.moved_or_copied();
20157 m_data.m_value.object->emplace(
20158 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20159 std::move((*element.m_data.m_value.array)[1]));
20164 // the initializer list describes an array -> create array
20165 m_data.m_type = value_t::array;
20166 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20170 assert_invariant();
20173 /// @brief explicitly create a binary array (without subtype)
20174 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20175 JSON_HEDLEY_WARN_UNUSED_RESULT
20176 static basic_json binary(const typename binary_t::container_type& init)
20178 auto res = basic_json();
20179 res.m_data.m_type = value_t::binary;
20180 res.m_data.m_value = init;
20184 /// @brief explicitly create a binary array (with subtype)
20185 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20186 JSON_HEDLEY_WARN_UNUSED_RESULT
20187 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20189 auto res = basic_json();
20190 res.m_data.m_type = value_t::binary;
20191 res.m_data.m_value = binary_t(init, subtype);
20195 /// @brief explicitly create a binary array
20196 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20197 JSON_HEDLEY_WARN_UNUSED_RESULT
20198 static basic_json binary(typename binary_t::container_type&& init)
20200 auto res = basic_json();
20201 res.m_data.m_type = value_t::binary;
20202 res.m_data.m_value = std::move(init);
20206 /// @brief explicitly create a binary array (with subtype)
20207 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20208 JSON_HEDLEY_WARN_UNUSED_RESULT
20209 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20211 auto res = basic_json();
20212 res.m_data.m_type = value_t::binary;
20213 res.m_data.m_value = binary_t(std::move(init), subtype);
20217 /// @brief explicitly create an array from an initializer list
20218 /// @sa https://json.nlohmann.me/api/basic_json/array/
20219 JSON_HEDLEY_WARN_UNUSED_RESULT
20220 static basic_json array(initializer_list_t init = {})
20222 return basic_json(init, false, value_t::array);
20225 /// @brief explicitly create an object from an initializer list
20226 /// @sa https://json.nlohmann.me/api/basic_json/object/
20227 JSON_HEDLEY_WARN_UNUSED_RESULT
20228 static basic_json object(initializer_list_t init = {})
20230 return basic_json(init, false, value_t::object);
20233 /// @brief construct an array with count copies of given value
20234 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20235 basic_json(size_type cnt, const basic_json& val):
20239 assert_invariant();
20242 /// @brief construct a JSON container given an iterator range
20243 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20244 template < class InputIT, typename std::enable_if <
20245 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20246 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20247 basic_json(InputIT first, InputIT last)
20249 JSON_ASSERT(first.m_object != nullptr);
20250 JSON_ASSERT(last.m_object != nullptr);
20252 // make sure iterator fits the current value
20253 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20255 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20258 // copy type from first iterator
20259 m_data.m_type = first.m_object->m_data.m_type;
20261 // check if iterator range is complete for primitive values
20262 switch (m_data.m_type)
20264 case value_t::boolean:
20265 case value_t::number_float:
20266 case value_t::number_integer:
20267 case value_t::number_unsigned:
20268 case value_t::string:
20270 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20271 || !last.m_it.primitive_iterator.is_end()))
20273 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20278 case value_t::null:
20279 case value_t::object:
20280 case value_t::array:
20281 case value_t::binary:
20282 case value_t::discarded:
20287 switch (m_data.m_type)
20289 case value_t::number_integer:
20291 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20295 case value_t::number_unsigned:
20297 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20301 case value_t::number_float:
20303 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20307 case value_t::boolean:
20309 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20313 case value_t::string:
20315 m_data.m_value = *first.m_object->m_data.m_value.string;
20319 case value_t::object:
20321 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20322 last.m_it.object_iterator);
20326 case value_t::array:
20328 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20329 last.m_it.array_iterator);
20333 case value_t::binary:
20335 m_data.m_value = *first.m_object->m_data.m_value.binary;
20339 case value_t::null:
20340 case value_t::discarded:
20342 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20346 assert_invariant();
20350 ///////////////////////////////////////
20351 // other constructors and destructor //
20352 ///////////////////////////////////////
20354 template<typename JsonRef,
20355 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20356 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20357 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20359 /// @brief copy constructor
20360 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20361 basic_json(const basic_json& other)
20362 : json_base_class_t(other)
20364 m_data.m_type = other.m_data.m_type;
20365 // check of passed value is valid
20366 other.assert_invariant();
20368 switch (m_data.m_type)
20370 case value_t::object:
20372 m_data.m_value = *other.m_data.m_value.object;
20376 case value_t::array:
20378 m_data.m_value = *other.m_data.m_value.array;
20382 case value_t::string:
20384 m_data.m_value = *other.m_data.m_value.string;
20388 case value_t::boolean:
20390 m_data.m_value = other.m_data.m_value.boolean;
20394 case value_t::number_integer:
20396 m_data.m_value = other.m_data.m_value.number_integer;
20400 case value_t::number_unsigned:
20402 m_data.m_value = other.m_data.m_value.number_unsigned;
20406 case value_t::number_float:
20408 m_data.m_value = other.m_data.m_value.number_float;
20412 case value_t::binary:
20414 m_data.m_value = *other.m_data.m_value.binary;
20418 case value_t::null:
20419 case value_t::discarded:
20425 assert_invariant();
20428 /// @brief move constructor
20429 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20430 basic_json(basic_json&& other) noexcept
20431 : json_base_class_t(std::forward<json_base_class_t>(other)),
20432 m_data(std::move(other.m_data))
20434 // check that passed value is valid
20435 other.assert_invariant(false);
20437 // invalidate payload
20438 other.m_data.m_type = value_t::null;
20439 other.m_data.m_value = {};
20442 assert_invariant();
20445 /// @brief copy assignment
20446 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
20447 basic_json& operator=(basic_json other) noexcept (
20448 std::is_nothrow_move_constructible<value_t>::value&&
20449 std::is_nothrow_move_assignable<value_t>::value&&
20450 std::is_nothrow_move_constructible<json_value>::value&&
20451 std::is_nothrow_move_assignable<json_value>::value&&
20452 std::is_nothrow_move_assignable<json_base_class_t>::value
20455 // check that passed value is valid
20456 other.assert_invariant();
20459 swap(m_data.m_type, other.m_data.m_type);
20460 swap(m_data.m_value, other.m_data.m_value);
20461 json_base_class_t::operator=(std::move(other));
20464 assert_invariant();
20468 /// @brief destructor
20469 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
20470 ~basic_json() noexcept
20472 assert_invariant(false);
20478 ///////////////////////
20479 // object inspection //
20480 ///////////////////////
20482 /// @name object inspection
20483 /// Functions to inspect the type of a JSON value.
20486 /// @brief serialization
20487 /// @sa https://json.nlohmann.me/api/basic_json/dump/
20488 string_t dump(const int indent = -1,
20489 const char indent_char = ' ',
20490 const bool ensure_ascii = false,
20491 const error_handler_t error_handler = error_handler_t::strict) const
20494 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20498 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20502 s.dump(*this, false, ensure_ascii, 0);
20508 /// @brief return the type of the JSON value (explicit)
20509 /// @sa https://json.nlohmann.me/api/basic_json/type/
20510 constexpr value_t type() const noexcept
20512 return m_data.m_type;
20515 /// @brief return whether type is primitive
20516 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
20517 constexpr bool is_primitive() const noexcept
20519 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20522 /// @brief return whether type is structured
20523 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
20524 constexpr bool is_structured() const noexcept
20526 return is_array() || is_object();
20529 /// @brief return whether value is null
20530 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
20531 constexpr bool is_null() const noexcept
20533 return m_data.m_type == value_t::null;
20536 /// @brief return whether value is a boolean
20537 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
20538 constexpr bool is_boolean() const noexcept
20540 return m_data.m_type == value_t::boolean;
20543 /// @brief return whether value is a number
20544 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
20545 constexpr bool is_number() const noexcept
20547 return is_number_integer() || is_number_float();
20550 /// @brief return whether value is an integer number
20551 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
20552 constexpr bool is_number_integer() const noexcept
20554 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20557 /// @brief return whether value is an unsigned integer number
20558 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
20559 constexpr bool is_number_unsigned() const noexcept
20561 return m_data.m_type == value_t::number_unsigned;
20564 /// @brief return whether value is a floating-point number
20565 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
20566 constexpr bool is_number_float() const noexcept
20568 return m_data.m_type == value_t::number_float;
20571 /// @brief return whether value is an object
20572 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
20573 constexpr bool is_object() const noexcept
20575 return m_data.m_type == value_t::object;
20578 /// @brief return whether value is an array
20579 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
20580 constexpr bool is_array() const noexcept
20582 return m_data.m_type == value_t::array;
20585 /// @brief return whether value is a string
20586 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
20587 constexpr bool is_string() const noexcept
20589 return m_data.m_type == value_t::string;
20592 /// @brief return whether value is a binary array
20593 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
20594 constexpr bool is_binary() const noexcept
20596 return m_data.m_type == value_t::binary;
20599 /// @brief return whether value is discarded
20600 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
20601 constexpr bool is_discarded() const noexcept
20603 return m_data.m_type == value_t::discarded;
20606 /// @brief return the type of the JSON value (implicit)
20607 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
20608 constexpr operator value_t() const noexcept
20610 return m_data.m_type;
20620 /// get a boolean (explicit)
20621 boolean_t get_impl(boolean_t* /*unused*/) const
20623 if (JSON_HEDLEY_LIKELY(is_boolean()))
20625 return m_data.m_value.boolean;
20628 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20631 /// get a pointer to the value (object)
20632 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20634 return is_object() ? m_data.m_value.object : nullptr;
20637 /// get a pointer to the value (object)
20638 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20640 return is_object() ? m_data.m_value.object : nullptr;
20643 /// get a pointer to the value (array)
20644 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20646 return is_array() ? m_data.m_value.array : nullptr;
20649 /// get a pointer to the value (array)
20650 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20652 return is_array() ? m_data.m_value.array : nullptr;
20655 /// get a pointer to the value (string)
20656 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20658 return is_string() ? m_data.m_value.string : nullptr;
20661 /// get a pointer to the value (string)
20662 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20664 return is_string() ? m_data.m_value.string : nullptr;
20667 /// get a pointer to the value (boolean)
20668 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20670 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20673 /// get a pointer to the value (boolean)
20674 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20676 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20679 /// get a pointer to the value (integer number)
20680 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20682 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20685 /// get a pointer to the value (integer number)
20686 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20688 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20691 /// get a pointer to the value (unsigned number)
20692 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20694 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20697 /// get a pointer to the value (unsigned number)
20698 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20700 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20703 /// get a pointer to the value (floating-point number)
20704 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20706 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20709 /// get a pointer to the value (floating-point number)
20710 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20712 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20715 /// get a pointer to the value (binary)
20716 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20718 return is_binary() ? m_data.m_value.binary : nullptr;
20721 /// get a pointer to the value (binary)
20722 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20724 return is_binary() ? m_data.m_value.binary : nullptr;
20728 @brief helper function to implement get_ref()
20730 This function helps to implement get_ref() without code duplication for
20731 const and non-const overloads
20733 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
20735 @throw type_error.303 if ReferenceType does not match underlying value
20736 type of the current JSON
20738 template<typename ReferenceType, typename ThisType>
20739 static ReferenceType get_ref_impl(ThisType& obj)
20741 // delegate the call to get_ptr<>()
20742 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20744 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20749 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20753 /// @name value access
20754 /// Direct access to the stored value of a JSON value.
20757 /// @brief get a pointer value (implicit)
20758 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20759 template<typename PointerType, typename std::enable_if<
20760 std::is_pointer<PointerType>::value, int>::type = 0>
20761 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20763 // delegate the call to get_impl_ptr<>()
20764 return get_impl_ptr(static_cast<PointerType>(nullptr));
20767 /// @brief get a pointer value (implicit)
20768 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
20769 template < typename PointerType, typename std::enable_if <
20770 std::is_pointer<PointerType>::value&&
20771 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20772 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20774 // delegate the call to get_impl_ptr<>() const
20775 return get_impl_ptr(static_cast<PointerType>(nullptr));
20780 @brief get a value (explicit)
20782 Explicit type conversion between the JSON value and a compatible value
20783 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20784 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20785 The value is converted by calling the @ref json_serializer<ValueType>
20786 `from_json()` method.
20788 The function is equivalent to executing
20791 JSONSerializer<ValueType>::from_json(*this, ret);
20795 This overloads is chosen if:
20796 - @a ValueType is not @ref basic_json,
20797 - @ref json_serializer<ValueType> has a `from_json()` method of the form
20798 `void from_json(const basic_json&, ValueType&)`, and
20799 - @ref json_serializer<ValueType> does not have a `from_json()` method of
20800 the form `ValueType from_json(const basic_json&)`
20802 @tparam ValueType the returned value type
20804 @return copy of the JSON value, converted to @a ValueType
20806 @throw what @ref json_serializer<ValueType> `from_json()` method throws
20808 @liveexample{The example below shows several conversions from JSON values
20809 to other types. There a few things to note: (1) Floating-point numbers can
20810 be converted to integers\, (2) A JSON array can be converted to a standard
20811 `std::vector<short>`\, (3) A JSON object can be converted to C++
20812 associative containers such as `std::unordered_map<std::string\,
20813 json>`.,get__ValueType_const}
20815 @since version 2.1.0
20817 template < typename ValueType,
20818 detail::enable_if_t <
20819 detail::is_default_constructible<ValueType>::value&&
20820 detail::has_from_json<basic_json_t, ValueType>::value,
20822 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20823 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20825 auto ret = ValueType();
20826 JSONSerializer<ValueType>::from_json(*this, ret);
20831 @brief get a value (explicit); special case
20833 Explicit type conversion between the JSON value and a compatible value
20834 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
20835 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
20836 The value is converted by calling the @ref json_serializer<ValueType>
20837 `from_json()` method.
20839 The function is equivalent to executing
20841 return JSONSerializer<ValueType>::from_json(*this);
20844 This overloads is chosen if:
20845 - @a ValueType is not @ref basic_json and
20846 - @ref json_serializer<ValueType> has a `from_json()` method of the form
20847 `ValueType from_json(const basic_json&)`
20849 @note If @ref json_serializer<ValueType> has both overloads of
20850 `from_json()`, this one is chosen.
20852 @tparam ValueType the returned value type
20854 @return copy of the JSON value, converted to @a ValueType
20856 @throw what @ref json_serializer<ValueType> `from_json()` method throws
20858 @since version 2.1.0
20860 template < typename ValueType,
20861 detail::enable_if_t <
20862 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
20864 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20865 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20867 return JSONSerializer<ValueType>::from_json(*this);
20871 @brief get special-case overload
20873 This overloads converts the current @ref basic_json in a different
20874 @ref basic_json type
20876 @tparam BasicJsonType == @ref basic_json
20878 @return a copy of *this, converted into @a BasicJsonType
20880 @complexity Depending on the implementation of the called `from_json()`
20883 @since version 3.2.0
20885 template < typename BasicJsonType,
20886 detail::enable_if_t <
20887 detail::is_basic_json<BasicJsonType>::value,
20889 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20895 @brief get special-case overload
20897 This overloads avoids a lot of template boilerplate, it can be seen as the
20900 @tparam BasicJsonType == @ref basic_json
20902 @return a copy of *this
20904 @complexity Constant.
20906 @since version 2.1.0
20908 template<typename BasicJsonType,
20909 detail::enable_if_t<
20910 std::is_same<BasicJsonType, basic_json_t>::value,
20912 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20918 @brief get a pointer value (explicit)
20921 template<typename PointerType,
20922 detail::enable_if_t<
20923 std::is_pointer<PointerType>::value,
20925 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
20926 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
20928 // delegate the call to get_ptr
20929 return get_ptr<PointerType>();
20934 @brief get a (pointer) value (explicit)
20936 Performs explicit type conversion between the JSON value and a compatible value if required.
20938 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
20939 No copies are made.
20941 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
20942 from the current @ref basic_json.
20944 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
20947 @tparam ValueTypeCV the provided value type
20948 @tparam ValueType the returned value type
20950 @return copy of the JSON value, converted to @tparam ValueType if necessary
20952 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
20954 @since version 2.1.0
20956 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
20957 #if defined(JSON_HAS_CPP_14)
20960 auto get() const noexcept(
20961 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
20962 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
20964 // we cannot static_assert on ValueTypeCV being non-const, because
20965 // there is support for get<const basic_json_t>(), which is why we
20966 // still need the uncvref
20967 static_assert(!std::is_reference<ValueTypeCV>::value,
20968 "get() cannot be used with reference types, you might want to use get_ref()");
20969 return get_impl<ValueType>(detail::priority_tag<4> {});
20973 @brief get a pointer value (explicit)
20975 Explicit pointer access to the internally stored JSON value. No copies are
20978 @warning The pointer becomes invalid if the underlying JSON object
20981 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
20982 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
20983 @ref number_unsigned_t, or @ref number_float_t.
20985 @return pointer to the internally stored JSON value if the requested
20986 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
20988 @complexity Constant.
20990 @liveexample{The example below shows how pointers to internal values of a
20991 JSON value can be requested. Note that no type conversions are made and a
20992 `nullptr` is returned if the value and the requested pointer type does not
20993 match.,get__PointerType}
20995 @sa see @ref get_ptr() for explicit pointer-member access
20997 @since version 1.0.0
20999 template<typename PointerType, typename std::enable_if<
21000 std::is_pointer<PointerType>::value, int>::type = 0>
21001 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21003 // delegate the call to get_ptr
21004 return get_ptr<PointerType>();
21007 /// @brief get a value (explicit)
21008 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
21009 template < typename ValueType,
21010 detail::enable_if_t <
21011 !detail::is_basic_json<ValueType>::value&&
21012 detail::has_from_json<basic_json_t, ValueType>::value,
21014 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21015 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21017 JSONSerializer<ValueType>::from_json(*this, v);
21021 // specialization to allow calling get_to with a basic_json value
21022 // see https://github.com/nlohmann/json/issues/2175
21023 template<typename ValueType,
21024 detail::enable_if_t <
21025 detail::is_basic_json<ValueType>::value,
21027 ValueType & get_to(ValueType& v) const
21034 typename T, std::size_t N,
21035 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21036 detail::enable_if_t <
21037 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21038 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21039 noexcept(noexcept(JSONSerializer<Array>::from_json(
21040 std::declval<const basic_json_t&>(), v)))
21042 JSONSerializer<Array>::from_json(*this, v);
21046 /// @brief get a reference value (implicit)
21047 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21048 template<typename ReferenceType, typename std::enable_if<
21049 std::is_reference<ReferenceType>::value, int>::type = 0>
21050 ReferenceType get_ref()
21052 // delegate call to get_ref_impl
21053 return get_ref_impl<ReferenceType>(*this);
21056 /// @brief get a reference value (implicit)
21057 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21058 template < typename ReferenceType, typename std::enable_if <
21059 std::is_reference<ReferenceType>::value&&
21060 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21061 ReferenceType get_ref() const
21063 // delegate call to get_ref_impl
21064 return get_ref_impl<ReferenceType>(*this);
21068 @brief get a value (implicit)
21070 Implicit type conversion between the JSON value and a compatible value.
21071 The call is realized by calling @ref get() const.
21073 @tparam ValueType non-pointer type compatible to the JSON value, for
21074 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21075 `std::vector` types for JSON arrays. The character type of @ref string_t
21076 as well as an initializer list of this type is excluded to avoid
21077 ambiguities as these types implicitly convert to `std::string`.
21079 @return copy of the JSON value, converted to type @a ValueType
21081 @throw type_error.302 in case passed type @a ValueType is incompatible
21082 to the JSON value type (e.g., the JSON value is of type boolean, but a
21083 string is requested); see example below
21085 @complexity Linear in the size of the JSON value.
21087 @liveexample{The example below shows several conversions from JSON values
21088 to other types. There a few things to note: (1) Floating-point numbers can
21089 be converted to integers\, (2) A JSON array can be converted to a standard
21090 `std::vector<short>`\, (3) A JSON object can be converted to C++
21091 associative containers such as `std::unordered_map<std::string\,
21092 json>`.,operator__ValueType}
21094 @since version 1.0.0
21096 template < typename ValueType, typename std::enable_if <
21097 detail::conjunction <
21098 detail::negation<std::is_pointer<ValueType>>,
21099 detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21100 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21101 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21102 detail::negation<detail::is_basic_json<ValueType>>,
21103 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21104 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21105 detail::negation<std::is_same<ValueType, std::string_view>>,
21107 #if defined(JSON_HAS_CPP_17)
21108 detail::negation<std::is_same<ValueType, std::any>>,
21110 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21111 >::value, int >::type = 0 >
21112 JSON_EXPLICIT operator ValueType() const
21114 // delegate the call to get<>() const
21115 return get<ValueType>();
21118 /// @brief get a binary value
21119 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21120 binary_t& get_binary()
21124 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21127 return *get_ptr<binary_t*>();
21130 /// @brief get a binary value
21131 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21132 const binary_t& get_binary() const
21136 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21139 return *get_ptr<const binary_t*>();
21145 ////////////////////
21146 // element access //
21147 ////////////////////
21149 /// @name element access
21150 /// Access to the JSON value.
21153 /// @brief access specified array element with bounds checking
21154 /// @sa https://json.nlohmann.me/api/basic_json/at/
21155 reference at(size_type idx)
21157 // at only works for arrays
21158 if (JSON_HEDLEY_LIKELY(is_array()))
21162 return set_parent(m_data.m_value.array->at(idx));
21164 JSON_CATCH (std::out_of_range&)
21166 // create better exception explanation
21167 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21172 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21176 /// @brief access specified array element with bounds checking
21177 /// @sa https://json.nlohmann.me/api/basic_json/at/
21178 const_reference at(size_type idx) const
21180 // at only works for arrays
21181 if (JSON_HEDLEY_LIKELY(is_array()))
21185 return m_data.m_value.array->at(idx);
21187 JSON_CATCH (std::out_of_range&)
21189 // create better exception explanation
21190 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21195 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21199 /// @brief access specified object element with bounds checking
21200 /// @sa https://json.nlohmann.me/api/basic_json/at/
21201 reference at(const typename object_t::key_type& key)
21203 // at only works for objects
21204 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21206 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21209 auto it = m_data.m_value.object->find(key);
21210 if (it == m_data.m_value.object->end())
21212 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21214 return set_parent(it->second);
21217 /// @brief access specified object element with bounds checking
21218 /// @sa https://json.nlohmann.me/api/basic_json/at/
21219 template<class KeyType, detail::enable_if_t<
21220 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21221 reference at(KeyType && key)
21223 // at only works for objects
21224 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21226 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21229 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21230 if (it == m_data.m_value.object->end())
21232 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21234 return set_parent(it->second);
21237 /// @brief access specified object element with bounds checking
21238 /// @sa https://json.nlohmann.me/api/basic_json/at/
21239 const_reference at(const typename object_t::key_type& key) const
21241 // at only works for objects
21242 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21244 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21247 auto it = m_data.m_value.object->find(key);
21248 if (it == m_data.m_value.object->end())
21250 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21255 /// @brief access specified object element with bounds checking
21256 /// @sa https://json.nlohmann.me/api/basic_json/at/
21257 template<class KeyType, detail::enable_if_t<
21258 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21259 const_reference at(KeyType && key) const
21261 // at only works for objects
21262 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21264 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21267 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21268 if (it == m_data.m_value.object->end())
21270 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21275 /// @brief access specified array element
21276 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21277 reference operator[](size_type idx)
21279 // implicitly convert null value to an empty array
21282 m_data.m_type = value_t::array;
21283 m_data.m_value.array = create<array_t>();
21284 assert_invariant();
21287 // operator[] only works for arrays
21288 if (JSON_HEDLEY_LIKELY(is_array()))
21290 // fill up array with null values if given idx is outside range
21291 if (idx >= m_data.m_value.array->size())
21293 #if JSON_DIAGNOSTICS
21294 // remember array size & capacity before resizing
21295 const auto old_size = m_data.m_value.array->size();
21296 const auto old_capacity = m_data.m_value.array->capacity();
21298 m_data.m_value.array->resize(idx + 1);
21300 #if JSON_DIAGNOSTICS
21301 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21303 // capacity has changed: update all parents
21308 // set parent for values added above
21309 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21312 assert_invariant();
21315 return m_data.m_value.array->operator[](idx);
21318 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21321 /// @brief access specified array element
21322 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21323 const_reference operator[](size_type idx) const
21325 // const operator[] only works for arrays
21326 if (JSON_HEDLEY_LIKELY(is_array()))
21328 return m_data.m_value.array->operator[](idx);
21331 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21334 /// @brief access specified object element
21335 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21336 reference operator[](typename object_t::key_type key)
21338 // implicitly convert null value to an empty object
21341 m_data.m_type = value_t::object;
21342 m_data.m_value.object = create<object_t>();
21343 assert_invariant();
21346 // operator[] only works for objects
21347 if (JSON_HEDLEY_LIKELY(is_object()))
21349 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21350 return set_parent(result.first->second);
21353 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21356 /// @brief access specified object element
21357 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21358 const_reference operator[](const typename object_t::key_type& key) const
21360 // const operator[] only works for objects
21361 if (JSON_HEDLEY_LIKELY(is_object()))
21363 auto it = m_data.m_value.object->find(key);
21364 JSON_ASSERT(it != m_data.m_value.object->end());
21368 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21371 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21372 // (they seemingly cannot be constrained to resolve the ambiguity)
21373 template<typename T>
21374 reference operator[](T* key)
21376 return operator[](typename object_t::key_type(key));
21379 template<typename T>
21380 const_reference operator[](T* key) const
21382 return operator[](typename object_t::key_type(key));
21385 /// @brief access specified object element
21386 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21387 template<class KeyType, detail::enable_if_t<
21388 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21389 reference operator[](KeyType && key)
21391 // implicitly convert null value to an empty object
21394 m_data.m_type = value_t::object;
21395 m_data.m_value.object = create<object_t>();
21396 assert_invariant();
21399 // operator[] only works for objects
21400 if (JSON_HEDLEY_LIKELY(is_object()))
21402 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21403 return set_parent(result.first->second);
21406 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21409 /// @brief access specified object element
21410 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21411 template<class KeyType, detail::enable_if_t<
21412 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21413 const_reference operator[](KeyType && key) const
21415 // const operator[] only works for objects
21416 if (JSON_HEDLEY_LIKELY(is_object()))
21418 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21419 JSON_ASSERT(it != m_data.m_value.object->end());
21423 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21427 template<typename KeyType>
21428 using is_comparable_with_object_key = detail::is_comparable <
21429 object_comparator_t, const typename object_t::key_type&, KeyType >;
21431 template<typename ValueType>
21432 using value_return_type = std::conditional <
21433 detail::is_c_string_uncvref<ValueType>::value,
21434 string_t, typename std::decay<ValueType>::type >;
21437 /// @brief access specified object element with default value
21438 /// @sa https://json.nlohmann.me/api/basic_json/value/
21439 template < class ValueType, detail::enable_if_t <
21440 !detail::is_transparent<object_comparator_t>::value
21441 && detail::is_getable<basic_json_t, ValueType>::value
21442 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21443 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21445 // value only works for objects
21446 if (JSON_HEDLEY_LIKELY(is_object()))
21448 // if key is found, return value and given default value otherwise
21449 const auto it = find(key);
21452 return it->template get<ValueType>();
21455 return default_value;
21458 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21461 /// @brief access specified object element with default value
21462 /// @sa https://json.nlohmann.me/api/basic_json/value/
21463 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21464 detail::enable_if_t <
21465 !detail::is_transparent<object_comparator_t>::value
21466 && detail::is_getable<basic_json_t, ReturnType>::value
21467 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21468 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21470 // value only works for objects
21471 if (JSON_HEDLEY_LIKELY(is_object()))
21473 // if key is found, return value and given default value otherwise
21474 const auto it = find(key);
21477 return it->template get<ReturnType>();
21480 return std::forward<ValueType>(default_value);
21483 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21486 /// @brief access specified object element with default value
21487 /// @sa https://json.nlohmann.me/api/basic_json/value/
21488 template < class ValueType, class KeyType, detail::enable_if_t <
21489 detail::is_transparent<object_comparator_t>::value
21490 && !detail::is_json_pointer<KeyType>::value
21491 && is_comparable_with_object_key<KeyType>::value
21492 && detail::is_getable<basic_json_t, ValueType>::value
21493 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21494 ValueType value(KeyType && key, const ValueType& default_value) const
21496 // value only works for objects
21497 if (JSON_HEDLEY_LIKELY(is_object()))
21499 // if key is found, return value and given default value otherwise
21500 const auto it = find(std::forward<KeyType>(key));
21503 return it->template get<ValueType>();
21506 return default_value;
21509 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21512 /// @brief access specified object element via JSON Pointer with default value
21513 /// @sa https://json.nlohmann.me/api/basic_json/value/
21514 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21515 detail::enable_if_t <
21516 detail::is_transparent<object_comparator_t>::value
21517 && !detail::is_json_pointer<KeyType>::value
21518 && is_comparable_with_object_key<KeyType>::value
21519 && detail::is_getable<basic_json_t, ReturnType>::value
21520 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21521 ReturnType value(KeyType && key, ValueType && default_value) const
21523 // value only works for objects
21524 if (JSON_HEDLEY_LIKELY(is_object()))
21526 // if key is found, return value and given default value otherwise
21527 const auto it = find(std::forward<KeyType>(key));
21530 return it->template get<ReturnType>();
21533 return std::forward<ValueType>(default_value);
21536 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21539 /// @brief access specified object element via JSON Pointer with default value
21540 /// @sa https://json.nlohmann.me/api/basic_json/value/
21541 template < class ValueType, detail::enable_if_t <
21542 detail::is_getable<basic_json_t, ValueType>::value
21543 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21544 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21546 // value only works for objects
21547 if (JSON_HEDLEY_LIKELY(is_object()))
21549 // if pointer resolves a value, return it or use default value
21552 return ptr.get_checked(this).template get<ValueType>();
21554 JSON_INTERNAL_CATCH (out_of_range&)
21556 return default_value;
21560 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21563 /// @brief access specified object element via JSON Pointer with default value
21564 /// @sa https://json.nlohmann.me/api/basic_json/value/
21565 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21566 detail::enable_if_t <
21567 detail::is_getable<basic_json_t, ReturnType>::value
21568 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21569 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21571 // value only works for objects
21572 if (JSON_HEDLEY_LIKELY(is_object()))
21574 // if pointer resolves a value, return it or use default value
21577 return ptr.get_checked(this).template get<ReturnType>();
21579 JSON_INTERNAL_CATCH (out_of_range&)
21581 return std::forward<ValueType>(default_value);
21585 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21588 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21589 detail::is_basic_json<BasicJsonType>::value
21590 && detail::is_getable<basic_json_t, ValueType>::value
21591 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21592 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21593 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21595 return value(ptr.convert(), default_value);
21598 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21599 detail::enable_if_t <
21600 detail::is_basic_json<BasicJsonType>::value
21601 && detail::is_getable<basic_json_t, ReturnType>::value
21602 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21603 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21604 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21606 return value(ptr.convert(), std::forward<ValueType>(default_value));
21609 /// @brief access the first element
21610 /// @sa https://json.nlohmann.me/api/basic_json/front/
21616 /// @brief access the first element
21617 /// @sa https://json.nlohmann.me/api/basic_json/front/
21618 const_reference front() const
21623 /// @brief access the last element
21624 /// @sa https://json.nlohmann.me/api/basic_json/back/
21632 /// @brief access the last element
21633 /// @sa https://json.nlohmann.me/api/basic_json/back/
21634 const_reference back() const
21641 /// @brief remove element given an iterator
21642 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21643 template < class IteratorType, detail::enable_if_t <
21644 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21645 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21646 IteratorType erase(IteratorType pos)
21648 // make sure iterator fits the current value
21649 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21651 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21654 IteratorType result = end();
21656 switch (m_data.m_type)
21658 case value_t::boolean:
21659 case value_t::number_float:
21660 case value_t::number_integer:
21661 case value_t::number_unsigned:
21662 case value_t::string:
21663 case value_t::binary:
21665 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21667 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21672 AllocatorType<string_t> alloc;
21673 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21674 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21675 m_data.m_value.string = nullptr;
21677 else if (is_binary())
21679 AllocatorType<binary_t> alloc;
21680 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21681 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21682 m_data.m_value.binary = nullptr;
21685 m_data.m_type = value_t::null;
21686 assert_invariant();
21690 case value_t::object:
21692 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21696 case value_t::array:
21698 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21702 case value_t::null:
21703 case value_t::discarded:
21705 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21711 /// @brief remove elements given an iterator range
21712 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21713 template < class IteratorType, detail::enable_if_t <
21714 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21715 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21716 IteratorType erase(IteratorType first, IteratorType last)
21718 // make sure iterator fits the current value
21719 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21721 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21724 IteratorType result = end();
21726 switch (m_data.m_type)
21728 case value_t::boolean:
21729 case value_t::number_float:
21730 case value_t::number_integer:
21731 case value_t::number_unsigned:
21732 case value_t::string:
21733 case value_t::binary:
21735 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21736 || !last.m_it.primitive_iterator.is_end()))
21738 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21743 AllocatorType<string_t> alloc;
21744 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21745 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21746 m_data.m_value.string = nullptr;
21748 else if (is_binary())
21750 AllocatorType<binary_t> alloc;
21751 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21752 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21753 m_data.m_value.binary = nullptr;
21756 m_data.m_type = value_t::null;
21757 assert_invariant();
21761 case value_t::object:
21763 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21764 last.m_it.object_iterator);
21768 case value_t::array:
21770 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21771 last.m_it.array_iterator);
21775 case value_t::null:
21776 case value_t::discarded:
21778 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21785 template < typename KeyType, detail::enable_if_t <
21786 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21787 size_type erase_internal(KeyType && key)
21789 // this erase only works for objects
21790 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21792 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21795 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21798 template < typename KeyType, detail::enable_if_t <
21799 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21800 size_type erase_internal(KeyType && key)
21802 // this erase only works for objects
21803 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21805 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21808 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21809 if (it != m_data.m_value.object->end())
21811 m_data.m_value.object->erase(it);
21819 /// @brief remove element from a JSON object given a key
21820 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21821 size_type erase(const typename object_t::key_type& key)
21823 // the indirection via erase_internal() is added to avoid making this
21824 // function a template and thus de-rank it during overload resolution
21825 return erase_internal(key);
21828 /// @brief remove element from a JSON object given a key
21829 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21830 template<class KeyType, detail::enable_if_t<
21831 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21832 size_type erase(KeyType && key)
21834 return erase_internal(std::forward<KeyType>(key));
21837 /// @brief remove element from a JSON array given an index
21838 /// @sa https://json.nlohmann.me/api/basic_json/erase/
21839 void erase(const size_type idx)
21841 // this erase only works for arrays
21842 if (JSON_HEDLEY_LIKELY(is_array()))
21844 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21846 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21849 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21853 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21867 /// @brief find an element in a JSON object
21868 /// @sa https://json.nlohmann.me/api/basic_json/find/
21869 iterator find(const typename object_t::key_type& key)
21871 auto result = end();
21875 result.m_it.object_iterator = m_data.m_value.object->find(key);
21881 /// @brief find an element in a JSON object
21882 /// @sa https://json.nlohmann.me/api/basic_json/find/
21883 const_iterator find(const typename object_t::key_type& key) const
21885 auto result = cend();
21889 result.m_it.object_iterator = m_data.m_value.object->find(key);
21895 /// @brief find an element in a JSON object
21896 /// @sa https://json.nlohmann.me/api/basic_json/find/
21897 template<class KeyType, detail::enable_if_t<
21898 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21899 iterator find(KeyType && key)
21901 auto result = end();
21905 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21911 /// @brief find an element in a JSON object
21912 /// @sa https://json.nlohmann.me/api/basic_json/find/
21913 template<class KeyType, detail::enable_if_t<
21914 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21915 const_iterator find(KeyType && key) const
21917 auto result = cend();
21921 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21927 /// @brief returns the number of occurrences of a key in a JSON object
21928 /// @sa https://json.nlohmann.me/api/basic_json/count/
21929 size_type count(const typename object_t::key_type& key) const
21931 // return 0 for all nonobject types
21932 return is_object() ? m_data.m_value.object->count(key) : 0;
21935 /// @brief returns the number of occurrences of a key in a JSON object
21936 /// @sa https://json.nlohmann.me/api/basic_json/count/
21937 template<class KeyType, detail::enable_if_t<
21938 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21939 size_type count(KeyType && key) const
21941 // return 0 for all nonobject types
21942 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
21945 /// @brief check the existence of an element in a JSON object
21946 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21947 bool contains(const typename object_t::key_type& key) const
21949 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
21952 /// @brief check the existence of an element in a JSON object
21953 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21954 template<class KeyType, detail::enable_if_t<
21955 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21956 bool contains(KeyType && key) const
21958 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
21961 /// @brief check the existence of an element in a JSON object given a JSON pointer
21962 /// @sa https://json.nlohmann.me/api/basic_json/contains/
21963 bool contains(const json_pointer& ptr) const
21965 return ptr.contains(this);
21968 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
21969 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21970 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
21972 return ptr.contains(this);
21982 /// @name iterators
21985 /// @brief returns an iterator to the first element
21986 /// @sa https://json.nlohmann.me/api/basic_json/begin/
21987 iterator begin() noexcept
21989 iterator result(this);
21990 result.set_begin();
21994 /// @brief returns an iterator to the first element
21995 /// @sa https://json.nlohmann.me/api/basic_json/begin/
21996 const_iterator begin() const noexcept
22001 /// @brief returns a const iterator to the first element
22002 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22003 const_iterator cbegin() const noexcept
22005 const_iterator result(this);
22006 result.set_begin();
22010 /// @brief returns an iterator to one past the last element
22011 /// @sa https://json.nlohmann.me/api/basic_json/end/
22012 iterator end() noexcept
22014 iterator result(this);
22019 /// @brief returns an iterator to one past the last element
22020 /// @sa https://json.nlohmann.me/api/basic_json/end/
22021 const_iterator end() const noexcept
22026 /// @brief returns an iterator to one past the last element
22027 /// @sa https://json.nlohmann.me/api/basic_json/cend/
22028 const_iterator cend() const noexcept
22030 const_iterator result(this);
22035 /// @brief returns an iterator to the reverse-beginning
22036 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22037 reverse_iterator rbegin() noexcept
22039 return reverse_iterator(end());
22042 /// @brief returns an iterator to the reverse-beginning
22043 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22044 const_reverse_iterator rbegin() const noexcept
22049 /// @brief returns an iterator to the reverse-end
22050 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22051 reverse_iterator rend() noexcept
22053 return reverse_iterator(begin());
22056 /// @brief returns an iterator to the reverse-end
22057 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22058 const_reverse_iterator rend() const noexcept
22063 /// @brief returns a const reverse iterator to the last element
22064 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22065 const_reverse_iterator crbegin() const noexcept
22067 return const_reverse_iterator(cend());
22070 /// @brief returns a const reverse iterator to one before the first
22071 /// @sa https://json.nlohmann.me/api/basic_json/crend/
22072 const_reverse_iterator crend() const noexcept
22074 return const_reverse_iterator(cbegin());
22078 /// @brief wrapper to access iterator member functions in range-based for
22079 /// @sa https://json.nlohmann.me/api/basic_json/items/
22080 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22081 /// version 4.0.0 of the library. Please use @ref items() instead;
22082 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22083 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22084 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22086 return ref.items();
22089 /// @brief wrapper to access iterator member functions in range-based for
22090 /// @sa https://json.nlohmann.me/api/basic_json/items/
22091 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22092 /// version 4.0.0 of the library. Please use @ref items() instead;
22093 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22094 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22095 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22097 return ref.items();
22100 /// @brief helper to access iterator member functions in range-based for
22101 /// @sa https://json.nlohmann.me/api/basic_json/items/
22102 iteration_proxy<iterator> items() noexcept
22104 return iteration_proxy<iterator>(*this);
22107 /// @brief helper to access iterator member functions in range-based for
22108 /// @sa https://json.nlohmann.me/api/basic_json/items/
22109 iteration_proxy<const_iterator> items() const noexcept
22111 return iteration_proxy<const_iterator>(*this);
22124 /// @brief checks whether the container is empty.
22125 /// @sa https://json.nlohmann.me/api/basic_json/empty/
22126 bool empty() const noexcept
22128 switch (m_data.m_type)
22130 case value_t::null:
22132 // null values are empty
22136 case value_t::array:
22138 // delegate call to array_t::empty()
22139 return m_data.m_value.array->empty();
22142 case value_t::object:
22144 // delegate call to object_t::empty()
22145 return m_data.m_value.object->empty();
22148 case value_t::string:
22149 case value_t::boolean:
22150 case value_t::number_integer:
22151 case value_t::number_unsigned:
22152 case value_t::number_float:
22153 case value_t::binary:
22154 case value_t::discarded:
22157 // all other types are nonempty
22163 /// @brief returns the number of elements
22164 /// @sa https://json.nlohmann.me/api/basic_json/size/
22165 size_type size() const noexcept
22167 switch (m_data.m_type)
22169 case value_t::null:
22171 // null values are empty
22175 case value_t::array:
22177 // delegate call to array_t::size()
22178 return m_data.m_value.array->size();
22181 case value_t::object:
22183 // delegate call to object_t::size()
22184 return m_data.m_value.object->size();
22187 case value_t::string:
22188 case value_t::boolean:
22189 case value_t::number_integer:
22190 case value_t::number_unsigned:
22191 case value_t::number_float:
22192 case value_t::binary:
22193 case value_t::discarded:
22196 // all other types have size 1
22202 /// @brief returns the maximum possible number of elements
22203 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
22204 size_type max_size() const noexcept
22206 switch (m_data.m_type)
22208 case value_t::array:
22210 // delegate call to array_t::max_size()
22211 return m_data.m_value.array->max_size();
22214 case value_t::object:
22216 // delegate call to object_t::max_size()
22217 return m_data.m_value.object->max_size();
22220 case value_t::null:
22221 case value_t::string:
22222 case value_t::boolean:
22223 case value_t::number_integer:
22224 case value_t::number_unsigned:
22225 case value_t::number_float:
22226 case value_t::binary:
22227 case value_t::discarded:
22230 // all other types have max_size() == size()
22243 /// @name modifiers
22246 /// @brief clears the contents
22247 /// @sa https://json.nlohmann.me/api/basic_json/clear/
22248 void clear() noexcept
22250 switch (m_data.m_type)
22252 case value_t::number_integer:
22254 m_data.m_value.number_integer = 0;
22258 case value_t::number_unsigned:
22260 m_data.m_value.number_unsigned = 0;
22264 case value_t::number_float:
22266 m_data.m_value.number_float = 0.0;
22270 case value_t::boolean:
22272 m_data.m_value.boolean = false;
22276 case value_t::string:
22278 m_data.m_value.string->clear();
22282 case value_t::binary:
22284 m_data.m_value.binary->clear();
22288 case value_t::array:
22290 m_data.m_value.array->clear();
22294 case value_t::object:
22296 m_data.m_value.object->clear();
22300 case value_t::null:
22301 case value_t::discarded:
22307 /// @brief add an object to an array
22308 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22309 void push_back(basic_json&& val)
22311 // push_back only works for null objects or arrays
22312 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22314 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22317 // transform null object into an array
22320 m_data.m_type = value_t::array;
22321 m_data.m_value = value_t::array;
22322 assert_invariant();
22325 // add element to array (move semantics)
22326 const auto old_capacity = m_data.m_value.array->capacity();
22327 m_data.m_value.array->push_back(std::move(val));
22328 set_parent(m_data.m_value.array->back(), old_capacity);
22329 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22332 /// @brief add an object to an array
22333 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22334 reference operator+=(basic_json&& val)
22336 push_back(std::move(val));
22340 /// @brief add an object to an array
22341 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22342 void push_back(const basic_json& val)
22344 // push_back only works for null objects or arrays
22345 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22347 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22350 // transform null object into an array
22353 m_data.m_type = value_t::array;
22354 m_data.m_value = value_t::array;
22355 assert_invariant();
22358 // add element to array
22359 const auto old_capacity = m_data.m_value.array->capacity();
22360 m_data.m_value.array->push_back(val);
22361 set_parent(m_data.m_value.array->back(), old_capacity);
22364 /// @brief add an object to an array
22365 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22366 reference operator+=(const basic_json& val)
22372 /// @brief add an object to an object
22373 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22374 void push_back(const typename object_t::value_type& val)
22376 // push_back only works for null objects or objects
22377 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22379 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22382 // transform null object into an object
22385 m_data.m_type = value_t::object;
22386 m_data.m_value = value_t::object;
22387 assert_invariant();
22390 // add element to object
22391 auto res = m_data.m_value.object->insert(val);
22392 set_parent(res.first->second);
22395 /// @brief add an object to an object
22396 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22397 reference operator+=(const typename object_t::value_type& val)
22403 /// @brief add an object to an object
22404 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22405 void push_back(initializer_list_t init)
22407 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22409 basic_json&& key = init.begin()->moved_or_copied();
22410 push_back(typename object_t::value_type(
22411 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22415 push_back(basic_json(init));
22419 /// @brief add an object to an object
22420 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22421 reference operator+=(initializer_list_t init)
22427 /// @brief add an object to an array
22428 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
22429 template<class... Args>
22430 reference emplace_back(Args&& ... args)
22432 // emplace_back only works for null objects or arrays
22433 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22435 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22438 // transform null object into an array
22441 m_data.m_type = value_t::array;
22442 m_data.m_value = value_t::array;
22443 assert_invariant();
22446 // add element to array (perfect forwarding)
22447 const auto old_capacity = m_data.m_value.array->capacity();
22448 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22449 return set_parent(m_data.m_value.array->back(), old_capacity);
22452 /// @brief add an object to an object if key does not exist
22453 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
22454 template<class... Args>
22455 std::pair<iterator, bool> emplace(Args&& ... args)
22457 // emplace only works for null objects or arrays
22458 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22460 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22463 // transform null object into an object
22466 m_data.m_type = value_t::object;
22467 m_data.m_value = value_t::object;
22468 assert_invariant();
22471 // add element to array (perfect forwarding)
22472 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22473 set_parent(res.first->second);
22475 // create result iterator and set iterator to the result of emplace
22477 it.m_it.object_iterator = res.first;
22479 // return pair of iterator and boolean
22480 return {it, res.second};
22483 /// Helper for insertion of an iterator
22484 /// @note: This uses std::distance to support GCC 4.8,
22485 /// see https://github.com/nlohmann/json/pull/1257
22486 template<typename... Args>
22487 iterator insert_iterator(const_iterator pos, Args&& ... args)
22489 iterator result(this);
22490 JSON_ASSERT(m_data.m_value.array != nullptr);
22492 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22493 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22494 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22496 // This could have been written as:
22497 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22498 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22504 /// @brief inserts element into array
22505 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22506 iterator insert(const_iterator pos, const basic_json& val)
22508 // insert only works for arrays
22509 if (JSON_HEDLEY_LIKELY(is_array()))
22511 // check if iterator pos fits to this JSON value
22512 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22514 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22517 // insert to array and return iterator
22518 return insert_iterator(pos, val);
22521 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22524 /// @brief inserts element into array
22525 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22526 iterator insert(const_iterator pos, basic_json&& val)
22528 return insert(pos, val);
22531 /// @brief inserts copies of element into array
22532 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22533 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
22535 // insert only works for arrays
22536 if (JSON_HEDLEY_LIKELY(is_array()))
22538 // check if iterator pos fits to this JSON value
22539 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22541 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22544 // insert to array and return iterator
22545 return insert_iterator(pos, cnt, val);
22548 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22551 /// @brief inserts range of elements into array
22552 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22553 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
22555 // insert only works for arrays
22556 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22558 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22561 // check if iterator pos fits to this JSON value
22562 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22564 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22567 // check if range iterators belong to the same JSON object
22568 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22570 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22573 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22575 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22578 // insert to array and return iterator
22579 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22582 /// @brief inserts elements from initializer list into array
22583 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22584 iterator insert(const_iterator pos, initializer_list_t ilist)
22586 // insert only works for arrays
22587 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22589 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22592 // check if iterator pos fits to this JSON value
22593 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22595 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22598 // insert to array and return iterator
22599 return insert_iterator(pos, ilist.begin(), ilist.end());
22602 /// @brief inserts range of elements into object
22603 /// @sa https://json.nlohmann.me/api/basic_json/insert/
22604 void insert(const_iterator first, const_iterator last)
22606 // insert only works for objects
22607 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22609 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22612 // check if range iterators belong to the same JSON object
22613 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22615 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22618 // passed iterators must belong to objects
22619 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22621 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22624 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22627 /// @brief updates a JSON object from another object, overwriting existing keys
22628 /// @sa https://json.nlohmann.me/api/basic_json/update/
22629 void update(const_reference j, bool merge_objects = false)
22631 update(j.begin(), j.end(), merge_objects);
22634 /// @brief updates a JSON object from another object, overwriting existing keys
22635 /// @sa https://json.nlohmann.me/api/basic_json/update/
22636 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22638 // implicitly convert null value to an empty object
22641 m_data.m_type = value_t::object;
22642 m_data.m_value.object = create<object_t>();
22643 assert_invariant();
22646 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22648 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22651 // check if range iterators belong to the same JSON object
22652 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22654 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22657 // passed iterators must belong to objects
22658 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22660 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22663 for (auto it = first; it != last; ++it)
22665 if (merge_objects && it.value().is_object())
22667 auto it2 = m_data.m_value.object->find(it.key());
22668 if (it2 != m_data.m_value.object->end())
22670 it2->second.update(it.value(), true);
22674 m_data.m_value.object->operator[](it.key()) = it.value();
22675 #if JSON_DIAGNOSTICS
22676 m_data.m_value.object->operator[](it.key()).m_parent = this;
22681 /// @brief exchanges the values
22682 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22683 void swap(reference other) noexcept (
22684 std::is_nothrow_move_constructible<value_t>::value&&
22685 std::is_nothrow_move_assignable<value_t>::value&&
22686 std::is_nothrow_move_constructible<json_value>::value&&
22687 std::is_nothrow_move_assignable<json_value>::value
22690 std::swap(m_data.m_type, other.m_data.m_type);
22691 std::swap(m_data.m_value, other.m_data.m_value);
22694 other.set_parents();
22695 assert_invariant();
22698 /// @brief exchanges the values
22699 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22700 friend void swap(reference left, reference right) noexcept (
22701 std::is_nothrow_move_constructible<value_t>::value&&
22702 std::is_nothrow_move_assignable<value_t>::value&&
22703 std::is_nothrow_move_constructible<json_value>::value&&
22704 std::is_nothrow_move_assignable<json_value>::value
22710 /// @brief exchanges the values
22711 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22712 void swap(array_t& other) // NOLINT(bugprone-exception-escape)
22714 // swap only works for arrays
22715 if (JSON_HEDLEY_LIKELY(is_array()))
22718 swap(*(m_data.m_value.array), other);
22722 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22726 /// @brief exchanges the values
22727 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22728 void swap(object_t& other) // NOLINT(bugprone-exception-escape)
22730 // swap only works for objects
22731 if (JSON_HEDLEY_LIKELY(is_object()))
22734 swap(*(m_data.m_value.object), other);
22738 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22742 /// @brief exchanges the values
22743 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22744 void swap(string_t& other) // NOLINT(bugprone-exception-escape)
22746 // swap only works for strings
22747 if (JSON_HEDLEY_LIKELY(is_string()))
22750 swap(*(m_data.m_value.string), other);
22754 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22758 /// @brief exchanges the values
22759 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22760 void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
22762 // swap only works for strings
22763 if (JSON_HEDLEY_LIKELY(is_binary()))
22766 swap(*(m_data.m_value.binary), other);
22770 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22774 /// @brief exchanges the values
22775 /// @sa https://json.nlohmann.me/api/basic_json/swap/
22776 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22778 // swap only works for strings
22779 if (JSON_HEDLEY_LIKELY(is_binary()))
22782 swap(*(m_data.m_value.binary), other);
22786 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22792 //////////////////////////////////////////
22793 // lexicographical comparison operators //
22794 //////////////////////////////////////////
22796 /// @name lexicographical comparison operators
22799 // note parentheses around operands are necessary; see
22800 // https://github.com/nlohmann/json/issues/1530
22801 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22802 const auto lhs_type = lhs.type(); \
22803 const auto rhs_type = rhs.type(); \
22805 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22807 switch (lhs_type) \
22809 case value_t::array: \
22810 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22812 case value_t::object: \
22813 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22815 case value_t::null: \
22816 return (null_result); \
22818 case value_t::string: \
22819 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22821 case value_t::boolean: \
22822 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22824 case value_t::number_integer: \
22825 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22827 case value_t::number_unsigned: \
22828 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22830 case value_t::number_float: \
22831 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22833 case value_t::binary: \
22834 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22836 case value_t::discarded: \
22838 return (unordered_result); \
22841 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22843 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22845 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22847 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22849 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22851 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22853 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22855 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22857 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22859 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22861 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22863 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22865 else if(compares_unordered(lhs, rhs))\
22867 return (unordered_result);\
22870 return (default_result);
22872 JSON_PRIVATE_UNLESS_TESTED:
22873 // returns true if:
22874 // - any operand is NaN and the other operand is of number type
22875 // - any operand is discarded
22876 // in legacy mode, discarded values are considered ordered if
22877 // an operation is computed as an odd number of inverses of others
22878 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22880 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22881 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22885 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22886 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22888 static_cast<void>(inverse);
22889 return lhs.is_discarded() || rhs.is_discarded();
22894 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22896 return compares_unordered(*this, rhs, inverse);
22900 #if JSON_HAS_THREE_WAY_COMPARISON
22901 /// @brief comparison: equal
22902 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22903 bool operator==(const_reference rhs) const noexcept
22906 #pragma GCC diagnostic push
22907 #pragma GCC diagnostic ignored "-Wfloat-equal"
22909 const_reference lhs = *this;
22910 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
22912 #pragma GCC diagnostic pop
22916 /// @brief comparison: equal
22917 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
22918 template<typename ScalarType>
22919 requires std::is_scalar_v<ScalarType>
22920 bool operator==(ScalarType rhs) const noexcept
22922 return *this == basic_json(rhs);
22925 /// @brief comparison: not equal
22926 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
22927 bool operator!=(const_reference rhs) const noexcept
22929 if (compares_unordered(rhs, true))
22933 return !operator==(rhs);
22936 /// @brief comparison: 3-way
22937 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
22938 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
22940 const_reference lhs = *this;
22941 // default_result is used if we cannot compare values. In that case,
22942 // we compare types.
22943 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
22944 std::partial_ordering::equivalent,
22945 std::partial_ordering::unordered,
22946 lhs_type <=> rhs_type) // *NOPAD*
22949 /// @brief comparison: 3-way
22950 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
22951 template<typename ScalarType>
22952 requires std::is_scalar_v<ScalarType>
22953 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
22955 return *this <=> basic_json(rhs); // *NOPAD*
22958 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22959 // all operators that are computed as an odd number of inverses of others
22960 // need to be overloaded to emulate the legacy comparison behavior
22962 /// @brief comparison: less than or equal
22963 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22964 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22965 bool operator<=(const_reference rhs) const noexcept
22967 if (compares_unordered(rhs, true))
22971 return !(rhs < *this);
22974 /// @brief comparison: less than or equal
22975 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
22976 template<typename ScalarType>
22977 requires std::is_scalar_v<ScalarType>
22978 bool operator<=(ScalarType rhs) const noexcept
22980 return *this <= basic_json(rhs);
22983 /// @brief comparison: greater than or equal
22984 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22985 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22986 bool operator>=(const_reference rhs) const noexcept
22988 if (compares_unordered(rhs, true))
22992 return !(*this < rhs);
22995 /// @brief comparison: greater than or equal
22996 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
22997 template<typename ScalarType>
22998 requires std::is_scalar_v<ScalarType>
22999 bool operator>=(ScalarType rhs) const noexcept
23001 return *this >= basic_json(rhs);
23005 /// @brief comparison: equal
23006 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23007 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23010 #pragma GCC diagnostic push
23011 #pragma GCC diagnostic ignored "-Wfloat-equal"
23013 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23015 #pragma GCC diagnostic pop
23019 /// @brief comparison: equal
23020 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23021 template<typename ScalarType, typename std::enable_if<
23022 std::is_scalar<ScalarType>::value, int>::type = 0>
23023 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23025 return lhs == basic_json(rhs);
23028 /// @brief comparison: equal
23029 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23030 template<typename ScalarType, typename std::enable_if<
23031 std::is_scalar<ScalarType>::value, int>::type = 0>
23032 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23034 return basic_json(lhs) == rhs;
23037 /// @brief comparison: not equal
23038 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23039 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23041 if (compares_unordered(lhs, rhs, true))
23045 return !(lhs == rhs);
23048 /// @brief comparison: not equal
23049 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23050 template<typename ScalarType, typename std::enable_if<
23051 std::is_scalar<ScalarType>::value, int>::type = 0>
23052 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23054 return lhs != basic_json(rhs);
23057 /// @brief comparison: not equal
23058 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23059 template<typename ScalarType, typename std::enable_if<
23060 std::is_scalar<ScalarType>::value, int>::type = 0>
23061 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23063 return basic_json(lhs) != rhs;
23066 /// @brief comparison: less than
23067 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23068 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23070 // default_result is used if we cannot compare values. In that case,
23071 // we compare types. Note we have to call the operator explicitly,
23072 // because MSVC has problems otherwise.
23073 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23076 /// @brief comparison: less than
23077 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23078 template<typename ScalarType, typename std::enable_if<
23079 std::is_scalar<ScalarType>::value, int>::type = 0>
23080 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23082 return lhs < basic_json(rhs);
23085 /// @brief comparison: less than
23086 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23087 template<typename ScalarType, typename std::enable_if<
23088 std::is_scalar<ScalarType>::value, int>::type = 0>
23089 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23091 return basic_json(lhs) < rhs;
23094 /// @brief comparison: less than or equal
23095 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23096 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23098 if (compares_unordered(lhs, rhs, true))
23102 return !(rhs < lhs);
23105 /// @brief comparison: less than or equal
23106 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23107 template<typename ScalarType, typename std::enable_if<
23108 std::is_scalar<ScalarType>::value, int>::type = 0>
23109 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23111 return lhs <= basic_json(rhs);
23114 /// @brief comparison: less than or equal
23115 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23116 template<typename ScalarType, typename std::enable_if<
23117 std::is_scalar<ScalarType>::value, int>::type = 0>
23118 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23120 return basic_json(lhs) <= rhs;
23123 /// @brief comparison: greater than
23124 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23125 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23128 if (compares_unordered(lhs, rhs))
23132 return !(lhs <= rhs);
23135 /// @brief comparison: greater than
23136 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23137 template<typename ScalarType, typename std::enable_if<
23138 std::is_scalar<ScalarType>::value, int>::type = 0>
23139 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23141 return lhs > basic_json(rhs);
23144 /// @brief comparison: greater than
23145 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23146 template<typename ScalarType, typename std::enable_if<
23147 std::is_scalar<ScalarType>::value, int>::type = 0>
23148 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23150 return basic_json(lhs) > rhs;
23153 /// @brief comparison: greater than or equal
23154 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23155 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23157 if (compares_unordered(lhs, rhs, true))
23161 return !(lhs < rhs);
23164 /// @brief comparison: greater than or equal
23165 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23166 template<typename ScalarType, typename std::enable_if<
23167 std::is_scalar<ScalarType>::value, int>::type = 0>
23168 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23170 return lhs >= basic_json(rhs);
23173 /// @brief comparison: greater than or equal
23174 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23175 template<typename ScalarType, typename std::enable_if<
23176 std::is_scalar<ScalarType>::value, int>::type = 0>
23177 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23179 return basic_json(lhs) >= rhs;
23183 #undef JSON_IMPLEMENT_OPERATOR
23187 ///////////////////
23188 // serialization //
23189 ///////////////////
23191 /// @name serialization
23194 /// @brief serialize to stream
23195 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23196 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23198 // read width member and use it as indentation parameter if nonzero
23199 const bool pretty_print = o.width() > 0;
23200 const auto indentation = pretty_print ? o.width() : 0;
23202 // reset width to 0 for subsequent calls to this stream
23205 // do the actual serialization
23206 serializer s(detail::output_adapter<char>(o), o.fill());
23207 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23211 /// @brief serialize to stream
23212 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23213 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
23214 /// version 4.0.0 of the library. Please use
23215 /// operator<<(std::ostream&, const basic_json&) instead; that is,
23216 /// replace calls like `j >> o;` with `o << j;`.
23217 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23218 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23222 #endif // JSON_NO_IO
23226 /////////////////////
23227 // deserialization //
23228 /////////////////////
23230 /// @name deserialization
23233 /// @brief deserialize from a compatible input
23234 /// @sa https://json.nlohmann.me/api/basic_json/parse/
23235 template<typename InputType>
23236 JSON_HEDLEY_WARN_UNUSED_RESULT
23237 static basic_json parse(InputType&& i,
23238 const parser_callback_t cb = nullptr,
23239 const bool allow_exceptions = true,
23240 const bool ignore_comments = false)
23243 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23247 /// @brief deserialize from a pair of character iterators
23248 /// @sa https://json.nlohmann.me/api/basic_json/parse/
23249 template<typename IteratorType>
23250 JSON_HEDLEY_WARN_UNUSED_RESULT
23251 static basic_json parse(IteratorType first,
23253 const parser_callback_t cb = nullptr,
23254 const bool allow_exceptions = true,
23255 const bool ignore_comments = false)
23258 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23262 JSON_HEDLEY_WARN_UNUSED_RESULT
23263 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23264 static basic_json parse(detail::span_input_adapter&& i,
23265 const parser_callback_t cb = nullptr,
23266 const bool allow_exceptions = true,
23267 const bool ignore_comments = false)
23270 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23274 /// @brief check if the input is valid JSON
23275 /// @sa https://json.nlohmann.me/api/basic_json/accept/
23276 template<typename InputType>
23277 static bool accept(InputType&& i,
23278 const bool ignore_comments = false)
23280 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23283 /// @brief check if the input is valid JSON
23284 /// @sa https://json.nlohmann.me/api/basic_json/accept/
23285 template<typename IteratorType>
23286 static bool accept(IteratorType first, IteratorType last,
23287 const bool ignore_comments = false)
23289 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23292 JSON_HEDLEY_WARN_UNUSED_RESULT
23293 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23294 static bool accept(detail::span_input_adapter&& i,
23295 const bool ignore_comments = false)
23297 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23300 /// @brief generate SAX events
23301 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23302 template <typename InputType, typename SAX>
23303 JSON_HEDLEY_NON_NULL(2)
23304 static bool sax_parse(InputType&& i, SAX* sax,
23305 input_format_t format = input_format_t::json,
23306 const bool strict = true,
23307 const bool ignore_comments = false)
23309 auto ia = detail::input_adapter(std::forward<InputType>(i));
23310 return format == input_format_t::json
23311 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23312 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23315 /// @brief generate SAX events
23316 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23317 template<class IteratorType, class SAX>
23318 JSON_HEDLEY_NON_NULL(3)
23319 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23320 input_format_t format = input_format_t::json,
23321 const bool strict = true,
23322 const bool ignore_comments = false)
23324 auto ia = detail::input_adapter(std::move(first), std::move(last));
23325 return format == input_format_t::json
23326 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23327 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23330 /// @brief generate SAX events
23331 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23332 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
23333 /// version 4.0.0 of the library. Please use
23334 /// sax_parse(ptr, ptr + len) instead.
23335 template <typename SAX>
23336 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23337 JSON_HEDLEY_NON_NULL(2)
23338 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23339 input_format_t format = input_format_t::json,
23340 const bool strict = true,
23341 const bool ignore_comments = false)
23344 return format == input_format_t::json
23345 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23346 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23347 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23348 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23351 /// @brief deserialize from stream
23352 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23353 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
23354 /// version 4.0.0 of the library. Please use
23355 /// operator>>(std::istream&, basic_json&) instead; that is,
23356 /// replace calls like `j << i;` with `i >> j;`.
23357 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23358 friend std::istream& operator<<(basic_json& j, std::istream& i)
23360 return operator>>(i, j);
23363 /// @brief deserialize from stream
23364 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23365 friend std::istream& operator>>(std::istream& i, basic_json& j)
23367 parser(detail::input_adapter(i)).parse(false, j);
23370 #endif // JSON_NO_IO
23373 ///////////////////////////
23374 // convenience functions //
23375 ///////////////////////////
23377 /// @brief return the type as string
23378 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
23379 JSON_HEDLEY_RETURNS_NON_NULL
23380 const char* type_name() const noexcept
23382 switch (m_data.m_type)
23384 case value_t::null:
23386 case value_t::object:
23388 case value_t::array:
23390 case value_t::string:
23392 case value_t::boolean:
23394 case value_t::binary:
23396 case value_t::discarded:
23397 return "discarded";
23398 case value_t::number_integer:
23399 case value_t::number_unsigned:
23400 case value_t::number_float:
23407 JSON_PRIVATE_UNLESS_TESTED:
23408 //////////////////////
23409 // member variables //
23410 //////////////////////
23414 /// the type of the current element
23415 value_t m_type = value_t::null;
23417 /// the value of the current element
23418 json_value m_value = {};
23420 data(const value_t v)
23421 : m_type(v), m_value(v)
23425 data(size_type cnt, const basic_json& val)
23426 : m_type(value_t::array)
23428 m_value.array = create<array_t>(cnt, val);
23431 data() noexcept = default;
23432 data(data&&) noexcept = default;
23433 data(const data&) noexcept = delete;
23434 data& operator=(data&&) noexcept = delete;
23435 data& operator=(const data&) noexcept = delete;
23439 m_value.destroy(m_type);
23445 #if JSON_DIAGNOSTICS
23446 /// a pointer to a parent value (for debugging purposes)
23447 basic_json* m_parent = nullptr;
23450 //////////////////////////////////////////
23451 // binary serialization/deserialization //
23452 //////////////////////////////////////////
23454 /// @name binary serialization/deserialization support
23458 /// @brief create a CBOR serialization of a given JSON value
23459 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23460 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23462 std::vector<std::uint8_t> result;
23463 to_cbor(j, result);
23467 /// @brief create a CBOR serialization of a given JSON value
23468 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23469 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23471 binary_writer<std::uint8_t>(o).write_cbor(j);
23474 /// @brief create a CBOR serialization of a given JSON value
23475 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23476 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23478 binary_writer<char>(o).write_cbor(j);
23481 /// @brief create a MessagePack serialization of a given JSON value
23482 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23483 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23485 std::vector<std::uint8_t> result;
23486 to_msgpack(j, result);
23490 /// @brief create a MessagePack serialization of a given JSON value
23491 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23492 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23494 binary_writer<std::uint8_t>(o).write_msgpack(j);
23497 /// @brief create a MessagePack serialization of a given JSON value
23498 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23499 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23501 binary_writer<char>(o).write_msgpack(j);
23504 /// @brief create a UBJSON serialization of a given JSON value
23505 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23506 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23507 const bool use_size = false,
23508 const bool use_type = false)
23510 std::vector<std::uint8_t> result;
23511 to_ubjson(j, result, use_size, use_type);
23515 /// @brief create a UBJSON serialization of a given JSON value
23516 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23517 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23518 const bool use_size = false, const bool use_type = false)
23520 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23523 /// @brief create a UBJSON serialization of a given JSON value
23524 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23525 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23526 const bool use_size = false, const bool use_type = false)
23528 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23531 /// @brief create a BJData serialization of a given JSON value
23532 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23533 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23534 const bool use_size = false,
23535 const bool use_type = false)
23537 std::vector<std::uint8_t> result;
23538 to_bjdata(j, result, use_size, use_type);
23542 /// @brief create a BJData serialization of a given JSON value
23543 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23544 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23545 const bool use_size = false, const bool use_type = false)
23547 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23550 /// @brief create a BJData serialization of a given JSON value
23551 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23552 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23553 const bool use_size = false, const bool use_type = false)
23555 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23558 /// @brief create a BSON serialization of a given JSON value
23559 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23560 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23562 std::vector<std::uint8_t> result;
23563 to_bson(j, result);
23567 /// @brief create a BSON serialization of a given JSON value
23568 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23569 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23571 binary_writer<std::uint8_t>(o).write_bson(j);
23574 /// @brief create a BSON serialization of a given JSON value
23575 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23576 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23578 binary_writer<char>(o).write_bson(j);
23581 /// @brief create a JSON value from an input in CBOR format
23582 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23583 template<typename InputType>
23584 JSON_HEDLEY_WARN_UNUSED_RESULT
23585 static basic_json from_cbor(InputType&& i,
23586 const bool strict = true,
23587 const bool allow_exceptions = true,
23588 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23591 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23592 auto ia = detail::input_adapter(std::forward<InputType>(i));
23593 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23594 return res ? result : basic_json(value_t::discarded);
23597 /// @brief create a JSON value from an input in CBOR format
23598 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23599 template<typename IteratorType>
23600 JSON_HEDLEY_WARN_UNUSED_RESULT
23601 static basic_json from_cbor(IteratorType first, IteratorType last,
23602 const bool strict = true,
23603 const bool allow_exceptions = true,
23604 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23607 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23608 auto ia = detail::input_adapter(std::move(first), std::move(last));
23609 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23610 return res ? result : basic_json(value_t::discarded);
23613 template<typename T>
23614 JSON_HEDLEY_WARN_UNUSED_RESULT
23615 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23616 static basic_json from_cbor(const T* ptr, std::size_t len,
23617 const bool strict = true,
23618 const bool allow_exceptions = true,
23619 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23621 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23625 JSON_HEDLEY_WARN_UNUSED_RESULT
23626 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23627 static basic_json from_cbor(detail::span_input_adapter&& i,
23628 const bool strict = true,
23629 const bool allow_exceptions = true,
23630 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23633 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23635 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23636 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23637 return res ? result : basic_json(value_t::discarded);
23640 /// @brief create a JSON value from an input in MessagePack format
23641 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23642 template<typename InputType>
23643 JSON_HEDLEY_WARN_UNUSED_RESULT
23644 static basic_json from_msgpack(InputType&& i,
23645 const bool strict = true,
23646 const bool allow_exceptions = true)
23649 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23650 auto ia = detail::input_adapter(std::forward<InputType>(i));
23651 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23652 return res ? result : basic_json(value_t::discarded);
23655 /// @brief create a JSON value from an input in MessagePack format
23656 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23657 template<typename IteratorType>
23658 JSON_HEDLEY_WARN_UNUSED_RESULT
23659 static basic_json from_msgpack(IteratorType first, IteratorType last,
23660 const bool strict = true,
23661 const bool allow_exceptions = true)
23664 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23665 auto ia = detail::input_adapter(std::move(first), std::move(last));
23666 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23667 return res ? result : basic_json(value_t::discarded);
23670 template<typename T>
23671 JSON_HEDLEY_WARN_UNUSED_RESULT
23672 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23673 static basic_json from_msgpack(const T* ptr, std::size_t len,
23674 const bool strict = true,
23675 const bool allow_exceptions = true)
23677 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23680 JSON_HEDLEY_WARN_UNUSED_RESULT
23681 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23682 static basic_json from_msgpack(detail::span_input_adapter&& i,
23683 const bool strict = true,
23684 const bool allow_exceptions = true)
23687 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23689 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23690 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23691 return res ? result : basic_json(value_t::discarded);
23694 /// @brief create a JSON value from an input in UBJSON format
23695 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23696 template<typename InputType>
23697 JSON_HEDLEY_WARN_UNUSED_RESULT
23698 static basic_json from_ubjson(InputType&& i,
23699 const bool strict = true,
23700 const bool allow_exceptions = true)
23703 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23704 auto ia = detail::input_adapter(std::forward<InputType>(i));
23705 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23706 return res ? result : basic_json(value_t::discarded);
23709 /// @brief create a JSON value from an input in UBJSON format
23710 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23711 template<typename IteratorType>
23712 JSON_HEDLEY_WARN_UNUSED_RESULT
23713 static basic_json from_ubjson(IteratorType first, IteratorType last,
23714 const bool strict = true,
23715 const bool allow_exceptions = true)
23718 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23719 auto ia = detail::input_adapter(std::move(first), std::move(last));
23720 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23721 return res ? result : basic_json(value_t::discarded);
23724 template<typename T>
23725 JSON_HEDLEY_WARN_UNUSED_RESULT
23726 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23727 static basic_json from_ubjson(const T* ptr, std::size_t len,
23728 const bool strict = true,
23729 const bool allow_exceptions = true)
23731 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23734 JSON_HEDLEY_WARN_UNUSED_RESULT
23735 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23736 static basic_json from_ubjson(detail::span_input_adapter&& i,
23737 const bool strict = true,
23738 const bool allow_exceptions = true)
23741 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23743 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23744 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23745 return res ? result : basic_json(value_t::discarded);
23749 /// @brief create a JSON value from an input in BJData format
23750 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23751 template<typename InputType>
23752 JSON_HEDLEY_WARN_UNUSED_RESULT
23753 static basic_json from_bjdata(InputType&& i,
23754 const bool strict = true,
23755 const bool allow_exceptions = true)
23758 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23759 auto ia = detail::input_adapter(std::forward<InputType>(i));
23760 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23761 return res ? result : basic_json(value_t::discarded);
23764 /// @brief create a JSON value from an input in BJData format
23765 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
23766 template<typename IteratorType>
23767 JSON_HEDLEY_WARN_UNUSED_RESULT
23768 static basic_json from_bjdata(IteratorType first, IteratorType last,
23769 const bool strict = true,
23770 const bool allow_exceptions = true)
23773 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23774 auto ia = detail::input_adapter(std::move(first), std::move(last));
23775 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23776 return res ? result : basic_json(value_t::discarded);
23779 /// @brief create a JSON value from an input in BSON format
23780 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23781 template<typename InputType>
23782 JSON_HEDLEY_WARN_UNUSED_RESULT
23783 static basic_json from_bson(InputType&& i,
23784 const bool strict = true,
23785 const bool allow_exceptions = true)
23788 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23789 auto ia = detail::input_adapter(std::forward<InputType>(i));
23790 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23791 return res ? result : basic_json(value_t::discarded);
23794 /// @brief create a JSON value from an input in BSON format
23795 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
23796 template<typename IteratorType>
23797 JSON_HEDLEY_WARN_UNUSED_RESULT
23798 static basic_json from_bson(IteratorType first, IteratorType last,
23799 const bool strict = true,
23800 const bool allow_exceptions = true)
23803 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23804 auto ia = detail::input_adapter(std::move(first), std::move(last));
23805 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23806 return res ? result : basic_json(value_t::discarded);
23809 template<typename T>
23810 JSON_HEDLEY_WARN_UNUSED_RESULT
23811 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23812 static basic_json from_bson(const T* ptr, std::size_t len,
23813 const bool strict = true,
23814 const bool allow_exceptions = true)
23816 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23819 JSON_HEDLEY_WARN_UNUSED_RESULT
23820 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23821 static basic_json from_bson(detail::span_input_adapter&& i,
23822 const bool strict = true,
23823 const bool allow_exceptions = true)
23826 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23828 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23829 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23830 return res ? result : basic_json(value_t::discarded);
23834 //////////////////////////
23835 // JSON Pointer support //
23836 //////////////////////////
23838 /// @name JSON Pointer functions
23841 /// @brief access specified element via JSON Pointer
23842 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23843 reference operator[](const json_pointer& ptr)
23845 return ptr.get_unchecked(this);
23848 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23849 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23850 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23852 return ptr.get_unchecked(this);
23855 /// @brief access specified element via JSON Pointer
23856 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
23857 const_reference operator[](const json_pointer& ptr) const
23859 return ptr.get_unchecked(this);
23862 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23863 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23864 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23866 return ptr.get_unchecked(this);
23869 /// @brief access specified element via JSON Pointer
23870 /// @sa https://json.nlohmann.me/api/basic_json/at/
23871 reference at(const json_pointer& ptr)
23873 return ptr.get_checked(this);
23876 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23877 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23878 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23880 return ptr.get_checked(this);
23883 /// @brief access specified element via JSON Pointer
23884 /// @sa https://json.nlohmann.me/api/basic_json/at/
23885 const_reference at(const json_pointer& ptr) const
23887 return ptr.get_checked(this);
23890 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23891 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23892 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23894 return ptr.get_checked(this);
23897 /// @brief return flattened JSON value
23898 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
23899 basic_json flatten() const
23901 basic_json result(value_t::object);
23902 json_pointer::flatten("", *this, result);
23906 /// @brief unflatten a previously flattened JSON value
23907 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
23908 basic_json unflatten() const
23910 return json_pointer::unflatten(*this);
23915 //////////////////////////
23916 // JSON Patch functions //
23917 //////////////////////////
23919 /// @name JSON Patch functions
23922 /// @brief applies a JSON patch in-place without copying the object
23923 /// @sa https://json.nlohmann.me/api/basic_json/patch/
23924 void patch_inplace(const basic_json& json_patch)
23926 basic_json& result = *this;
23927 // the valid JSON Patch operations
23928 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
23930 const auto get_op = [](const std::string & op)
23934 return patch_operations::add;
23936 if (op == "remove")
23938 return patch_operations::remove;
23940 if (op == "replace")
23942 return patch_operations::replace;
23946 return patch_operations::move;
23950 return patch_operations::copy;
23954 return patch_operations::test;
23957 return patch_operations::invalid;
23960 // wrapper for "add" operation; add value at ptr
23961 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
23963 // adding to the root of the target document means replacing it
23970 // make sure the top element of the pointer exists
23971 json_pointer const top_pointer = ptr.top();
23972 if (top_pointer != ptr)
23974 result.at(top_pointer);
23977 // get reference to parent of JSON pointer ptr
23978 const auto last_path = ptr.back();
23980 // parent must exist when performing patch add per RFC6902 specs
23981 basic_json& parent = result.at(ptr);
23983 switch (parent.m_data.m_type)
23985 case value_t::null:
23986 case value_t::object:
23988 // use operator[] to add value
23989 parent[last_path] = val;
23993 case value_t::array:
23995 if (last_path == "-")
23997 // special case: append to back
23998 parent.push_back(val);
24002 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24003 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24005 // avoid undefined behavior
24006 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24009 // default case: insert add offset
24010 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24015 // if there exists a parent it cannot be primitive
24016 case value_t::string: // LCOV_EXCL_LINE
24017 case value_t::boolean: // LCOV_EXCL_LINE
24018 case value_t::number_integer: // LCOV_EXCL_LINE
24019 case value_t::number_unsigned: // LCOV_EXCL_LINE
24020 case value_t::number_float: // LCOV_EXCL_LINE
24021 case value_t::binary: // LCOV_EXCL_LINE
24022 case value_t::discarded: // LCOV_EXCL_LINE
24023 default: // LCOV_EXCL_LINE
24024 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24028 // wrapper for "remove" operation; remove value at ptr
24029 const auto operation_remove = [this, &result](json_pointer & ptr)
24031 // get reference to parent of JSON pointer ptr
24032 const auto last_path = ptr.back();
24034 basic_json& parent = result.at(ptr);
24037 if (parent.is_object())
24039 // perform range check
24040 auto it = parent.find(last_path);
24041 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24047 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24050 else if (parent.is_array())
24052 // note erase performs range check
24053 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24057 // type check: top level value must be an array
24058 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24060 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24063 // iterate and apply the operations
24064 for (const auto& val : json_patch)
24066 // wrapper to get a value for an operation
24067 const auto get_value = [&val](const std::string & op,
24068 const std::string & member,
24069 bool string_type) -> basic_json &
24072 auto it = val.m_data.m_value.object->find(member);
24074 // context-sensitive error message
24075 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24077 // check if desired value is present
24078 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24080 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24081 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24084 // check if result is of type string
24085 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24087 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24088 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24091 // no error: return value
24095 // type check: every element of the array must be an object
24096 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24098 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24101 // collect mandatory members
24102 const auto op = get_value("op", "op", true).template get<std::string>();
24103 const auto path = get_value(op, "path", true).template get<std::string>();
24104 json_pointer ptr(path);
24106 switch (get_op(op))
24108 case patch_operations::add:
24110 operation_add(ptr, get_value("add", "value", false));
24114 case patch_operations::remove:
24116 operation_remove(ptr);
24120 case patch_operations::replace:
24122 // the "path" location must exist - use at()
24123 result.at(ptr) = get_value("replace", "value", false);
24127 case patch_operations::move:
24129 const auto from_path = get_value("move", "from", true).template get<std::string>();
24130 json_pointer from_ptr(from_path);
24132 // the "from" location must exist - use at()
24133 basic_json const v = result.at(from_ptr);
24135 // The move operation is functionally identical to a
24136 // "remove" operation on the "from" location, followed
24137 // immediately by an "add" operation at the target
24138 // location with the value that was just removed.
24139 operation_remove(from_ptr);
24140 operation_add(ptr, v);
24144 case patch_operations::copy:
24146 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24147 const json_pointer from_ptr(from_path);
24149 // the "from" location must exist - use at()
24150 basic_json const v = result.at(from_ptr);
24152 // The copy is functionally identical to an "add"
24153 // operation at the target location using the value
24154 // specified in the "from" member.
24155 operation_add(ptr, v);
24159 case patch_operations::test:
24161 bool success = false;
24164 // check if "value" matches the one at "path"
24165 // the "path" location must exist - use at()
24166 success = (result.at(ptr) == get_value("test", "value", false));
24168 JSON_INTERNAL_CATCH (out_of_range&)
24170 // ignore out of range errors: success remains false
24173 // throw an exception if test fails
24174 if (JSON_HEDLEY_UNLIKELY(!success))
24176 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24182 case patch_operations::invalid:
24185 // op must be "add", "remove", "replace", "move", "copy", or
24187 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24193 /// @brief applies a JSON patch to a copy of the current object
24194 /// @sa https://json.nlohmann.me/api/basic_json/patch/
24195 basic_json patch(const basic_json& json_patch) const
24197 basic_json result = *this;
24198 result.patch_inplace(json_patch);
24202 /// @brief creates a diff as a JSON patch
24203 /// @sa https://json.nlohmann.me/api/basic_json/diff/
24204 JSON_HEDLEY_WARN_UNUSED_RESULT
24205 static basic_json diff(const basic_json& source, const basic_json& target,
24206 const std::string& path = "")
24209 basic_json result(value_t::array);
24211 // if the values are the same, return empty patch
24212 if (source == target)
24217 if (source.type() != target.type())
24219 // different types: replace value
24222 {"op", "replace"}, {"path", path}, {"value", target}
24227 switch (source.type())
24229 case value_t::array:
24231 // first pass: traverse common elements
24233 while (i < source.size() && i < target.size())
24235 // recursive call to compare array values at index i
24236 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24237 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24241 // We now reached the end of at least one array
24242 // in a second pass, traverse the remaining elements
24244 // remove my remaining elements
24245 const auto end_index = static_cast<difference_type>(result.size());
24246 while (i < source.size())
24248 // add operations in reverse order to avoid invalid
24250 result.insert(result.begin() + end_index, object(
24253 {"path", detail::concat(path, '/', std::to_string(i))}
24258 // add other remaining elements
24259 while (i < target.size())
24264 {"path", detail::concat(path, "/-")},
24265 {"value", target[i]}
24273 case value_t::object:
24275 // first pass: traverse this object's elements
24276 for (auto it = source.cbegin(); it != source.cend(); ++it)
24278 // escape the key name to be used in a JSON patch
24279 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24281 if (target.find(it.key()) != target.end())
24283 // recursive call to compare object values at key it
24284 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24285 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24289 // found a key that is not in o -> remove it
24290 result.push_back(object(
24292 {"op", "remove"}, {"path", path_key}
24297 // second pass: traverse other object's elements
24298 for (auto it = target.cbegin(); it != target.cend(); ++it)
24300 if (source.find(it.key()) == source.end())
24302 // found a key that is not in this -> add it
24303 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24306 {"op", "add"}, {"path", path_key},
24307 {"value", it.value()}
24315 case value_t::null:
24316 case value_t::string:
24317 case value_t::boolean:
24318 case value_t::number_integer:
24319 case value_t::number_unsigned:
24320 case value_t::number_float:
24321 case value_t::binary:
24322 case value_t::discarded:
24325 // both primitive type: replace value
24328 {"op", "replace"}, {"path", path}, {"value", target}
24338 ////////////////////////////////
24339 // JSON Merge Patch functions //
24340 ////////////////////////////////
24342 /// @name JSON Merge Patch functions
24345 /// @brief applies a JSON Merge Patch
24346 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
24347 void merge_patch(const basic_json& apply_patch)
24349 if (apply_patch.is_object())
24355 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24357 if (it.value().is_null())
24363 operator[](it.key()).merge_patch(it.value());
24369 *this = apply_patch;
24376 /// @brief user-defined to_string function for JSON values
24377 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
24378 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24379 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24384 inline namespace literals
24386 inline namespace json_literals
24389 /// @brief user-defined string literal for JSON values
24390 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
24391 JSON_HEDLEY_NON_NULL(1)
24392 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24394 return nlohmann::json::parse(s, s + n);
24397 /// @brief user-defined string literal for JSON pointer
24398 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
24399 JSON_HEDLEY_NON_NULL(1)
24400 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24402 return nlohmann::json::json_pointer(std::string(s, n));
24405 } // namespace json_literals
24406 } // namespace literals
24407 NLOHMANN_JSON_NAMESPACE_END
24409 ///////////////////////
24410 // nonmember support //
24411 ///////////////////////
24413 namespace std // NOLINT(cert-dcl58-cpp)
24416 /// @brief hash value for JSON objects
24417 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
24418 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24419 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24421 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24423 return nlohmann::detail::hash(j);
24427 // specialization for std::less<value_t>
24429 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24432 @brief compare two value_t enum values
24433 @since version 3.0.0
24435 bool operator()(::nlohmann::detail::value_t lhs,
24436 ::nlohmann::detail::value_t rhs) const noexcept
24438 #if JSON_HAS_THREE_WAY_COMPARISON
24439 return std::is_lt(lhs <=> rhs); // *NOPAD*
24441 return ::nlohmann::detail::operator<(lhs, rhs);
24446 // C++20 prohibit function specialization in the std namespace.
24447 #ifndef JSON_HAS_CPP_20
24449 /// @brief exchanges the values of two JSON objects
24450 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
24451 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24452 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24453 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
24454 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24463 #if JSON_USE_GLOBAL_UDLS
24464 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24465 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24468 // #include <nlohmann/detail/macro_unscope.hpp>
24469 // __ _____ _____ _____
24470 // __| | __| | | | JSON for Modern C++
24471 // | | |__ | | | | | | version 3.11.2
24472 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
24474 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24475 // SPDX-License-Identifier: MIT
24479 // restore clang diagnostic settings
24480 #if defined(__clang__)
24481 #pragma clang diagnostic pop
24486 #undef JSON_INTERNAL_CATCH
24488 #undef JSON_PRIVATE_UNLESS_TESTED
24489 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24490 #undef NLOHMANN_BASIC_JSON_TPL
24491 #undef JSON_EXPLICIT
24492 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24493 #undef JSON_INLINE_VARIABLE
24494 #undef JSON_NO_UNIQUE_ADDRESS
24495 #undef JSON_DISABLE_ENUM_SERIALIZATION
24496 #undef JSON_USE_GLOBAL_UDLS
24498 #ifndef JSON_TEST_KEEP_MACROS
24501 #undef JSON_HAS_CPP_11
24502 #undef JSON_HAS_CPP_14
24503 #undef JSON_HAS_CPP_17
24504 #undef JSON_HAS_CPP_20
24505 #undef JSON_HAS_FILESYSTEM
24506 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24507 #undef JSON_HAS_THREE_WAY_COMPARISON
24508 #undef JSON_HAS_RANGES
24509 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24512 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24513 // __ _____ _____ _____
24514 // __| | __| | | | JSON for Modern C++
24515 // | | |__ | | | | | | version 3.11.2
24516 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
24518 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
24519 // SPDX-License-Identifier: MIT
24523 #undef JSON_HEDLEY_ALWAYS_INLINE
24524 #undef JSON_HEDLEY_ARM_VERSION
24525 #undef JSON_HEDLEY_ARM_VERSION_CHECK
24526 #undef JSON_HEDLEY_ARRAY_PARAM
24527 #undef JSON_HEDLEY_ASSUME
24528 #undef JSON_HEDLEY_BEGIN_C_DECLS
24529 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24530 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24531 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24532 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24533 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24534 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
24535 #undef JSON_HEDLEY_CLANG_HAS_WARNING
24536 #undef JSON_HEDLEY_COMPCERT_VERSION
24537 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24538 #undef JSON_HEDLEY_CONCAT
24539 #undef JSON_HEDLEY_CONCAT3
24540 #undef JSON_HEDLEY_CONCAT3_EX
24541 #undef JSON_HEDLEY_CONCAT_EX
24542 #undef JSON_HEDLEY_CONST
24543 #undef JSON_HEDLEY_CONSTEXPR
24544 #undef JSON_HEDLEY_CONST_CAST
24545 #undef JSON_HEDLEY_CPP_CAST
24546 #undef JSON_HEDLEY_CRAY_VERSION
24547 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
24548 #undef JSON_HEDLEY_C_DECL
24549 #undef JSON_HEDLEY_DEPRECATED
24550 #undef JSON_HEDLEY_DEPRECATED_FOR
24551 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24552 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24553 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24554 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24555 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24556 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24557 #undef JSON_HEDLEY_DIAGNOSTIC_POP
24558 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24559 #undef JSON_HEDLEY_DMC_VERSION
24560 #undef JSON_HEDLEY_DMC_VERSION_CHECK
24561 #undef JSON_HEDLEY_EMPTY_BASES
24562 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24563 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24564 #undef JSON_HEDLEY_END_C_DECLS
24565 #undef JSON_HEDLEY_FLAGS
24566 #undef JSON_HEDLEY_FLAGS_CAST
24567 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24568 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
24569 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24570 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24571 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
24572 #undef JSON_HEDLEY_GCC_HAS_FEATURE
24573 #undef JSON_HEDLEY_GCC_HAS_WARNING
24574 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24575 #undef JSON_HEDLEY_GCC_VERSION
24576 #undef JSON_HEDLEY_GCC_VERSION_CHECK
24577 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24578 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24579 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24580 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24581 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24582 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
24583 #undef JSON_HEDLEY_GNUC_HAS_WARNING
24584 #undef JSON_HEDLEY_GNUC_VERSION
24585 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
24586 #undef JSON_HEDLEY_HAS_ATTRIBUTE
24587 #undef JSON_HEDLEY_HAS_BUILTIN
24588 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24589 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24590 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24591 #undef JSON_HEDLEY_HAS_EXTENSION
24592 #undef JSON_HEDLEY_HAS_FEATURE
24593 #undef JSON_HEDLEY_HAS_WARNING
24594 #undef JSON_HEDLEY_IAR_VERSION
24595 #undef JSON_HEDLEY_IAR_VERSION_CHECK
24596 #undef JSON_HEDLEY_IBM_VERSION
24597 #undef JSON_HEDLEY_IBM_VERSION_CHECK
24598 #undef JSON_HEDLEY_IMPORT
24599 #undef JSON_HEDLEY_INLINE
24600 #undef JSON_HEDLEY_INTEL_CL_VERSION
24601 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24602 #undef JSON_HEDLEY_INTEL_VERSION
24603 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
24604 #undef JSON_HEDLEY_IS_CONSTANT
24605 #undef JSON_HEDLEY_IS_CONSTEXPR_
24606 #undef JSON_HEDLEY_LIKELY
24607 #undef JSON_HEDLEY_MALLOC
24608 #undef JSON_HEDLEY_MCST_LCC_VERSION
24609 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24610 #undef JSON_HEDLEY_MESSAGE
24611 #undef JSON_HEDLEY_MSVC_VERSION
24612 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
24613 #undef JSON_HEDLEY_NEVER_INLINE
24614 #undef JSON_HEDLEY_NON_NULL
24615 #undef JSON_HEDLEY_NO_ESCAPE
24616 #undef JSON_HEDLEY_NO_RETURN
24617 #undef JSON_HEDLEY_NO_THROW
24618 #undef JSON_HEDLEY_NULL
24619 #undef JSON_HEDLEY_PELLES_VERSION
24620 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
24621 #undef JSON_HEDLEY_PGI_VERSION
24622 #undef JSON_HEDLEY_PGI_VERSION_CHECK
24623 #undef JSON_HEDLEY_PREDICT
24624 #undef JSON_HEDLEY_PRINTF_FORMAT
24625 #undef JSON_HEDLEY_PRIVATE
24626 #undef JSON_HEDLEY_PUBLIC
24627 #undef JSON_HEDLEY_PURE
24628 #undef JSON_HEDLEY_REINTERPRET_CAST
24629 #undef JSON_HEDLEY_REQUIRE
24630 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24631 #undef JSON_HEDLEY_REQUIRE_MSG
24632 #undef JSON_HEDLEY_RESTRICT
24633 #undef JSON_HEDLEY_RETURNS_NON_NULL
24634 #undef JSON_HEDLEY_SENTINEL
24635 #undef JSON_HEDLEY_STATIC_ASSERT
24636 #undef JSON_HEDLEY_STATIC_CAST
24637 #undef JSON_HEDLEY_STRINGIFY
24638 #undef JSON_HEDLEY_STRINGIFY_EX
24639 #undef JSON_HEDLEY_SUNPRO_VERSION
24640 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24641 #undef JSON_HEDLEY_TINYC_VERSION
24642 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
24643 #undef JSON_HEDLEY_TI_ARMCL_VERSION
24644 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24645 #undef JSON_HEDLEY_TI_CL2000_VERSION
24646 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24647 #undef JSON_HEDLEY_TI_CL430_VERSION
24648 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24649 #undef JSON_HEDLEY_TI_CL6X_VERSION
24650 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24651 #undef JSON_HEDLEY_TI_CL7X_VERSION
24652 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24653 #undef JSON_HEDLEY_TI_CLPRU_VERSION
24654 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24655 #undef JSON_HEDLEY_TI_VERSION
24656 #undef JSON_HEDLEY_TI_VERSION_CHECK
24657 #undef JSON_HEDLEY_UNAVAILABLE
24658 #undef JSON_HEDLEY_UNLIKELY
24659 #undef JSON_HEDLEY_UNPREDICTABLE
24660 #undef JSON_HEDLEY_UNREACHABLE
24661 #undef JSON_HEDLEY_UNREACHABLE_RETURN
24662 #undef JSON_HEDLEY_VERSION
24663 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24664 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
24665 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
24666 #undef JSON_HEDLEY_VERSION_ENCODE
24667 #undef JSON_HEDLEY_WARNING
24668 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
24669 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24670 #undef JSON_HEDLEY_FALL_THROUGH
24674 #endif // INCLUDE_NLOHMANN_JSON_HPP_