Seregon/Hermes

Hermes/Dyforge is a program written in c++ allows you to inject a dll that can analyze all processes in a program, can be used for mod and reverse engeneering

C/3.8 KB/No license
DyForge/include/nlohmann/json.hpp
Hermes / DyForge / include / nlohmann / json.hpp
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8 
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17 
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20 
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33 
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.12.0
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42 
43 
44 
45#include <utility>
46 
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.12.0
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55 
56 
57 
58// This file contains all macro definitions affecting or depending on the ABI
59 
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67 
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
71 
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75 
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77 #define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79 
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83 
84#if JSON_DIAGNOSTICS
85 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89 
90#if JSON_DIAGNOSTIC_POSITIONS
91 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95 
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101 
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105 
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110 
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116 
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122 
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131 
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136 
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143 
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153 
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159 
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.12.0
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168 
169 
170 
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#ifdef JSON_HAS_CPP_17
177 #include <optional> // optional
178#endif
179#include <string> // string
180#include <tuple> // tuple, make_tuple
181#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
182#include <unordered_map> // unordered_map
183#include <utility> // pair, declval
184#include <valarray> // valarray
185 
186// #include <nlohmann/detail/exceptions.hpp>
187// __ _____ _____ _____
188// __| | __| | | | JSON for Modern C++
189// | | |__ | | | | | | version 3.12.0
190// |_____|_____|_____|_|___| https://github.com/nlohmann/json
191//
192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
193// SPDX-License-Identifier: MIT
194 
195 
196 
197#include <cstddef> // nullptr_t
198#include <exception> // exception
199#if JSON_DIAGNOSTICS
200 #include <numeric> // accumulate
201#endif
202#include <stdexcept> // runtime_error
203#include <string> // to_string
204#include <vector> // vector
205 
206// #include <nlohmann/detail/value_t.hpp>
207// __ _____ _____ _____
208// __| | __| | | | JSON for Modern C++
209// | | |__ | | | | | | version 3.12.0
210// |_____|_____|_____|_|___| https://github.com/nlohmann/json
211//
212// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
213// SPDX-License-Identifier: MIT
214 
215 
216 
217#include <array> // array
218#include <cstddef> // size_t
219#include <cstdint> // uint8_t
220#include <string> // string
221 
222// #include <nlohmann/detail/macro_scope.hpp>
223// __ _____ _____ _____
224// __| | __| | | | JSON for Modern C++
225// | | |__ | | | | | | version 3.12.0
226// |_____|_____|_____|_|___| https://github.com/nlohmann/json
227//
228// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
229// SPDX-License-Identifier: MIT
230 
231 
232 
233#include <utility> // declval, pair
234// #include <nlohmann/detail/meta/detected.hpp>
235// __ _____ _____ _____
236// __| | __| | | | JSON for Modern C++
237// | | |__ | | | | | | version 3.12.0
238// |_____|_____|_____|_|___| https://github.com/nlohmann/json
239//
240// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
241// SPDX-License-Identifier: MIT
242 
243 
244 
245#include <type_traits>
246 
247// #include <nlohmann/detail/meta/void_t.hpp>
248// __ _____ _____ _____
249// __| | __| | | | JSON for Modern C++
250// | | |__ | | | | | | version 3.12.0
251// |_____|_____|_____|_|___| https://github.com/nlohmann/json
252//
253// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
254// SPDX-License-Identifier: MIT
255 
256 
257 
258// #include <nlohmann/detail/abi_macros.hpp>
259 
260 
261NLOHMANN_JSON_NAMESPACE_BEGIN
262namespace detail
263{
264 
265template<typename ...Ts> struct make_void
266{
267 using type = void;
268};
269template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
270 
271} // namespace detail
272NLOHMANN_JSON_NAMESPACE_END
273 
274 
275NLOHMANN_JSON_NAMESPACE_BEGIN
276namespace detail
277{
278 
279// https://en.cppreference.com/w/cpp/experimental/is_detected
280struct nonesuch
281{
282 nonesuch() = delete;
283 ~nonesuch() = delete;
284 nonesuch(nonesuch const&) = delete;
285 nonesuch(nonesuch const&&) = delete;
286 void operator=(nonesuch const&) = delete;
287 void operator=(nonesuch&&) = delete;
288};
289 
290template<class Default,
291 class AlwaysVoid,
292 template<class...> class Op,
293 class... Args>
294struct detector
295{
296 using value_t = std::false_type;
297 using type = Default;
298};
299 
300template<class Default, template<class...> class Op, class... Args>
301struct detector<Default, void_t<Op<Args...>>, Op, Args...>
302{
303 using value_t = std::true_type;
304 using type = Op<Args...>;
305};
306 
307template<template<class...> class Op, class... Args>
308using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
309 
310template<template<class...> class Op, class... Args>
311struct is_detected_lazy : is_detected<Op, Args...> { };
312 
313template<template<class...> class Op, class... Args>
314using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
315 
316template<class Default, template<class...> class Op, class... Args>
317using detected_or = detector<Default, void, Op, Args...>;
318 
319template<class Default, template<class...> class Op, class... Args>
320using detected_or_t = typename detected_or<Default, Op, Args...>::type;
321 
322template<class Expected, template<class...> class Op, class... Args>
323using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
324 
325template<class To, template<class...> class Op, class... Args>
326using is_detected_convertible =
327 std::is_convertible<detected_t<Op, Args...>, To>;
328 
329} // namespace detail
330NLOHMANN_JSON_NAMESPACE_END
331 
332// #include <nlohmann/thirdparty/hedley/hedley.hpp>
333 
334 
335// __ _____ _____ _____
336// __| | __| | | | JSON for Modern C++
337// | | |__ | | | | | | version 3.12.0
338// |_____|_____|_____|_|___| https://github.com/nlohmann/json
339//
340// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
341// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
342// SPDX-License-Identifier: MIT
343 
344/* Hedley - https://nemequ.github.io/hedley
345 * Created by Evan Nemerson <evan@nemerson.com>
346 */
347 
348#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
349#if defined(JSON_HEDLEY_VERSION)
350 #undef JSON_HEDLEY_VERSION
351#endif
352#define JSON_HEDLEY_VERSION 15
353 
354#if defined(JSON_HEDLEY_STRINGIFY_EX)
355 #undef JSON_HEDLEY_STRINGIFY_EX
356#endif
357#define JSON_HEDLEY_STRINGIFY_EX(x) #x
358 
359#if defined(JSON_HEDLEY_STRINGIFY)
360 #undef JSON_HEDLEY_STRINGIFY
361#endif
362#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
363 
364#if defined(JSON_HEDLEY_CONCAT_EX)
365 #undef JSON_HEDLEY_CONCAT_EX
366#endif
367#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
368 
369#if defined(JSON_HEDLEY_CONCAT)
370 #undef JSON_HEDLEY_CONCAT
371#endif
372#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
373 
374#if defined(JSON_HEDLEY_CONCAT3_EX)
375 #undef JSON_HEDLEY_CONCAT3_EX
376#endif
377#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
378 
379#if defined(JSON_HEDLEY_CONCAT3)
380 #undef JSON_HEDLEY_CONCAT3
381#endif
382#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
383 
384#if defined(JSON_HEDLEY_VERSION_ENCODE)
385 #undef JSON_HEDLEY_VERSION_ENCODE
386#endif
387#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
388 
389#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
390 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
391#endif
392#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
393 
394#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
395 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
396#endif
397#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
398 
399#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
400 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
401#endif
402#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
403 
404#if defined(JSON_HEDLEY_GNUC_VERSION)
405 #undef JSON_HEDLEY_GNUC_VERSION
406#endif
407#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
408 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
409#elif defined(__GNUC__)
410 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
411#endif
412 
413#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
414 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
415#endif
416#if defined(JSON_HEDLEY_GNUC_VERSION)
417 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
418#else
419 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
420#endif
421 
422#if defined(JSON_HEDLEY_MSVC_VERSION)
423 #undef JSON_HEDLEY_MSVC_VERSION
424#endif
425#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
426 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
427#elif defined(_MSC_FULL_VER) && !defined(__ICL)
428 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
429#elif defined(_MSC_VER) && !defined(__ICL)
430 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
431#endif
432 
433#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
434 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
435#endif
436#if !defined(JSON_HEDLEY_MSVC_VERSION)
437 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
438#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
439 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
440#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
441 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
442#else
443 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
444#endif
445 
446#if defined(JSON_HEDLEY_INTEL_VERSION)
447 #undef JSON_HEDLEY_INTEL_VERSION
448#endif
449#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
450 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
451#elif defined(__INTEL_COMPILER) && !defined(__ICL)
452 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
453#endif
454 
455#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
456 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
457#endif
458#if defined(JSON_HEDLEY_INTEL_VERSION)
459 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
460#else
461 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
462#endif
463 
464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465 #undef JSON_HEDLEY_INTEL_CL_VERSION
466#endif
467#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
468 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
469#endif
470 
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
472 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
473#endif
474#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
475 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
476#else
477 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
478#endif
479 
480#if defined(JSON_HEDLEY_PGI_VERSION)
481 #undef JSON_HEDLEY_PGI_VERSION
482#endif
483#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
484 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
485#endif
486 
487#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
488 #undef JSON_HEDLEY_PGI_VERSION_CHECK
489#endif
490#if defined(JSON_HEDLEY_PGI_VERSION)
491 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
492#else
493 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
494#endif
495 
496#if defined(JSON_HEDLEY_SUNPRO_VERSION)
497 #undef JSON_HEDLEY_SUNPRO_VERSION
498#endif
499#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
500 #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)
501#elif defined(__SUNPRO_C)
502 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
503#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
504 #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)
505#elif defined(__SUNPRO_CC)
506 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
507#endif
508 
509#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
510 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
511#endif
512#if defined(JSON_HEDLEY_SUNPRO_VERSION)
513 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
514#else
515 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
516#endif
517 
518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
520#endif
521#if defined(__EMSCRIPTEN__)
522 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
523#endif
524 
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
526 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
527#endif
528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
529 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
530#else
531 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
532#endif
533 
534#if defined(JSON_HEDLEY_ARM_VERSION)
535 #undef JSON_HEDLEY_ARM_VERSION
536#endif
537#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
538 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
539#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
540 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
541#endif
542 
543#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
544 #undef JSON_HEDLEY_ARM_VERSION_CHECK
545#endif
546#if defined(JSON_HEDLEY_ARM_VERSION)
547 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
548#else
549 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
550#endif
551 
552#if defined(JSON_HEDLEY_IBM_VERSION)
553 #undef JSON_HEDLEY_IBM_VERSION
554#endif
555#if defined(__ibmxl__)
556 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
557#elif defined(__xlC__) && defined(__xlC_ver__)
558 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
559#elif defined(__xlC__)
560 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
561#endif
562 
563#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
564 #undef JSON_HEDLEY_IBM_VERSION_CHECK
565#endif
566#if defined(JSON_HEDLEY_IBM_VERSION)
567 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
568#else
569 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
570#endif
571 
572#if defined(JSON_HEDLEY_TI_VERSION)
573 #undef JSON_HEDLEY_TI_VERSION
574#endif
575#if \
576 defined(__TI_COMPILER_VERSION__) && \
577 ( \
578 defined(__TMS470__) || defined(__TI_ARM__) || \
579 defined(__MSP430__) || \
580 defined(__TMS320C2000__) \
581 )
582#if (__TI_COMPILER_VERSION__ >= 16000000)
583 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
584#endif
585#endif
586 
587#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
588 #undef JSON_HEDLEY_TI_VERSION_CHECK
589#endif
590#if defined(JSON_HEDLEY_TI_VERSION)
591 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
592#else
593 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
594#endif
595 
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597 #undef JSON_HEDLEY_TI_CL2000_VERSION
598#endif
599#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
600 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
601#endif
602 
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
604 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
605#endif
606#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
607 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
608#else
609 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
610#endif
611 
612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
613 #undef JSON_HEDLEY_TI_CL430_VERSION
614#endif
615#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
616 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
617#endif
618 
619#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
620 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
621#endif
622#if defined(JSON_HEDLEY_TI_CL430_VERSION)
623 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
624#else
625 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
626#endif
627 
628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629 #undef JSON_HEDLEY_TI_ARMCL_VERSION
630#endif
631#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
632 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
633#endif
634 
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
636 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
637#endif
638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
639 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
640#else
641 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
642#endif
643 
644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645 #undef JSON_HEDLEY_TI_CL6X_VERSION
646#endif
647#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
648 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
649#endif
650 
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
652 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
653#endif
654#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
655 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
656#else
657 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
658#endif
659 
660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661 #undef JSON_HEDLEY_TI_CL7X_VERSION
662#endif
663#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
664 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
665#endif
666 
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
668 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
669#endif
670#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
671 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
672#else
673 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
674#endif
675 
676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677 #undef JSON_HEDLEY_TI_CLPRU_VERSION
678#endif
679#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
680 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
681#endif
682 
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
684 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
685#endif
686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
687 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
688#else
689 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
690#endif
691 
692#if defined(JSON_HEDLEY_CRAY_VERSION)
693 #undef JSON_HEDLEY_CRAY_VERSION
694#endif
695#if defined(_CRAYC)
696 #if defined(_RELEASE_PATCHLEVEL)
697 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
698 #else
699 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
700 #endif
701#endif
702 
703#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
704 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
705#endif
706#if defined(JSON_HEDLEY_CRAY_VERSION)
707 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
708#else
709 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
710#endif
711 
712#if defined(JSON_HEDLEY_IAR_VERSION)
713 #undef JSON_HEDLEY_IAR_VERSION
714#endif
715#if defined(__IAR_SYSTEMS_ICC__)
716 #if __VER__ > 1000
717 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
718 #else
719 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
720 #endif
721#endif
722 
723#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
724 #undef JSON_HEDLEY_IAR_VERSION_CHECK
725#endif
726#if defined(JSON_HEDLEY_IAR_VERSION)
727 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
728#else
729 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
730#endif
731 
732#if defined(JSON_HEDLEY_TINYC_VERSION)
733 #undef JSON_HEDLEY_TINYC_VERSION
734#endif
735#if defined(__TINYC__)
736 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
737#endif
738 
739#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
740 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
741#endif
742#if defined(JSON_HEDLEY_TINYC_VERSION)
743 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
744#else
745 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
746#endif
747 
748#if defined(JSON_HEDLEY_DMC_VERSION)
749 #undef JSON_HEDLEY_DMC_VERSION
750#endif
751#if defined(__DMC__)
752 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
753#endif
754 
755#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
756 #undef JSON_HEDLEY_DMC_VERSION_CHECK
757#endif
758#if defined(JSON_HEDLEY_DMC_VERSION)
759 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
760#else
761 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
762#endif
763 
764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
765 #undef JSON_HEDLEY_COMPCERT_VERSION
766#endif
767#if defined(__COMPCERT_VERSION__)
768 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
769#endif
770 
771#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
772 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
773#endif
774#if defined(JSON_HEDLEY_COMPCERT_VERSION)
775 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
776#else
777 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
778#endif
779 
780#if defined(JSON_HEDLEY_PELLES_VERSION)
781 #undef JSON_HEDLEY_PELLES_VERSION
782#endif
783#if defined(__POCC__)
784 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
785#endif
786 
787#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
788 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
789#endif
790#if defined(JSON_HEDLEY_PELLES_VERSION)
791 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
792#else
793 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
794#endif
795 
796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797 #undef JSON_HEDLEY_MCST_LCC_VERSION
798#endif
799#if defined(__LCC__) && defined(__LCC_MINOR__)
800 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
801#endif
802 
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
804 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
805#endif
806#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
807 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
808#else
809 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
810#endif
811 
812#if defined(JSON_HEDLEY_GCC_VERSION)
813 #undef JSON_HEDLEY_GCC_VERSION
814#endif
815#if \
816 defined(JSON_HEDLEY_GNUC_VERSION) && \
817 !defined(__clang__) && \
818 !defined(JSON_HEDLEY_INTEL_VERSION) && \
819 !defined(JSON_HEDLEY_PGI_VERSION) && \
820 !defined(JSON_HEDLEY_ARM_VERSION) && \
821 !defined(JSON_HEDLEY_CRAY_VERSION) && \
822 !defined(JSON_HEDLEY_TI_VERSION) && \
823 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
827 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
828 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
829 !defined(__COMPCERT__) && \
830 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
831 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
832#endif
833 
834#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
835 #undef JSON_HEDLEY_GCC_VERSION_CHECK
836#endif
837#if defined(JSON_HEDLEY_GCC_VERSION)
838 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
839#else
840 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
841#endif
842 
843#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
844 #undef JSON_HEDLEY_HAS_ATTRIBUTE
845#endif
846#if \
847 defined(__has_attribute) && \
848 ( \
849 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
850 )
851# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
852#else
853# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
854#endif
855 
856#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
857 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
858#endif
859#if defined(__has_attribute)
860 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
861#else
862 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863#endif
864 
865#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
866 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
867#endif
868#if defined(__has_attribute)
869 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
870#else
871 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872#endif
873 
874#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
875 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
876#endif
877#if \
878 defined(__has_cpp_attribute) && \
879 defined(__cplusplus) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
881 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
882#else
883 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
884#endif
885 
886#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
887 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
888#endif
889#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
890 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
891#elif \
892 !defined(JSON_HEDLEY_PGI_VERSION) && \
893 !defined(JSON_HEDLEY_IAR_VERSION) && \
894 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
895 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
896 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
897#else
898 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
899#endif
900 
901#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
902 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
903#endif
904#if defined(__has_cpp_attribute) && defined(__cplusplus)
905 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
906#else
907 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
908#endif
909 
910#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
911 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
912#endif
913#if defined(__has_cpp_attribute) && defined(__cplusplus)
914 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
915#else
916 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
917#endif
918 
919#if defined(JSON_HEDLEY_HAS_BUILTIN)
920 #undef JSON_HEDLEY_HAS_BUILTIN
921#endif
922#if defined(__has_builtin)
923 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
924#else
925 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
926#endif
927 
928#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
929 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
930#endif
931#if defined(__has_builtin)
932 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
933#else
934 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
935#endif
936 
937#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
938 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
939#endif
940#if defined(__has_builtin)
941 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
942#else
943 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
944#endif
945 
946#if defined(JSON_HEDLEY_HAS_FEATURE)
947 #undef JSON_HEDLEY_HAS_FEATURE
948#endif
949#if defined(__has_feature)
950 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
951#else
952 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
953#endif
954 
955#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
956 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
957#endif
958#if defined(__has_feature)
959 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
960#else
961 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
962#endif
963 
964#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
965 #undef JSON_HEDLEY_GCC_HAS_FEATURE
966#endif
967#if defined(__has_feature)
968 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
969#else
970 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
971#endif
972 
973#if defined(JSON_HEDLEY_HAS_EXTENSION)
974 #undef JSON_HEDLEY_HAS_EXTENSION
975#endif
976#if defined(__has_extension)
977 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
978#else
979 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
980#endif
981 
982#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
983 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
984#endif
985#if defined(__has_extension)
986 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
987#else
988 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
989#endif
990 
991#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
992 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
993#endif
994#if defined(__has_extension)
995 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
996#else
997 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
998#endif
999 
1000#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1001 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1002#endif
1003#if defined(__has_declspec_attribute)
1004 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1005#else
1006 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1007#endif
1008 
1009#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1010 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1011#endif
1012#if defined(__has_declspec_attribute)
1013 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1014#else
1015 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1016#endif
1017 
1018#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1019 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1020#endif
1021#if defined(__has_declspec_attribute)
1022 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1023#else
1024 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1025#endif
1026 
1027#if defined(JSON_HEDLEY_HAS_WARNING)
1028 #undef JSON_HEDLEY_HAS_WARNING
1029#endif
1030#if defined(__has_warning)
1031 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1032#else
1033 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1034#endif
1035 
1036#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1037 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1038#endif
1039#if defined(__has_warning)
1040 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1041#else
1042 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1043#endif
1044 
1045#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1046 #undef JSON_HEDLEY_GCC_HAS_WARNING
1047#endif
1048#if defined(__has_warning)
1049 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1050#else
1051 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1052#endif
1053 
1054#if \
1055 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1056 defined(__clang__) || \
1057 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1058 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1059 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1060 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1061 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1062 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1063 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1064 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1065 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1066 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1067 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1068 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1069 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1070 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1071 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1072 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1073 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1074#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1075 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1076#else
1077 #define JSON_HEDLEY_PRAGMA(value)
1078#endif
1079 
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1082#endif
1083#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1084 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1085#endif
1086#if defined(__clang__)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1089#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1092#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1093 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1094 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1095#elif \
1096 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1097 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1100#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1101 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1102 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1103#elif \
1104 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1105 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1106 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1107 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1108 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1109 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1112#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1115#else
1116 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1117 #define JSON_HEDLEY_DIAGNOSTIC_POP
1118#endif
1119 
1120/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1121 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1122#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1123 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1124#endif
1125#if defined(__cplusplus)
1126# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1127# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1128# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1129# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1130 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1131 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1132 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1133 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1134 xpr \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1136# else
1137# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1138 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1139 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1140 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1141 xpr \
1142 JSON_HEDLEY_DIAGNOSTIC_POP
1143# endif
1144# else
1145# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1146 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1147 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1148 xpr \
1149 JSON_HEDLEY_DIAGNOSTIC_POP
1150# endif
1151# endif
1152#endif
1153#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1154 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1155#endif
1156 
1157#if defined(JSON_HEDLEY_CONST_CAST)
1158 #undef JSON_HEDLEY_CONST_CAST
1159#endif
1160#if defined(__cplusplus)
1161# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1162#elif \
1163 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1164 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1165 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1166# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1167 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1168 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1169 ((T) (expr)); \
1170 JSON_HEDLEY_DIAGNOSTIC_POP \
1171 }))
1172#else
1173# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1174#endif
1175 
1176#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1177 #undef JSON_HEDLEY_REINTERPRET_CAST
1178#endif
1179#if defined(__cplusplus)
1180 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1181#else
1182 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1183#endif
1184 
1185#if defined(JSON_HEDLEY_STATIC_CAST)
1186 #undef JSON_HEDLEY_STATIC_CAST
1187#endif
1188#if defined(__cplusplus)
1189 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1190#else
1191 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1192#endif
1193 
1194#if defined(JSON_HEDLEY_CPP_CAST)
1195 #undef JSON_HEDLEY_CPP_CAST
1196#endif
1197#if defined(__cplusplus)
1198# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1199# define JSON_HEDLEY_CPP_CAST(T, expr) \
1200 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1201 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1202 ((T) (expr)) \
1203 JSON_HEDLEY_DIAGNOSTIC_POP
1204# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1205# define JSON_HEDLEY_CPP_CAST(T, expr) \
1206 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1207 _Pragma("diag_suppress=Pe137") \
1208 JSON_HEDLEY_DIAGNOSTIC_POP
1209# else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1211# endif
1212#else
1213# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1214#endif
1215 
1216#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1217 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1218#endif
1219#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1221#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1223#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1225#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1226 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1227#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1228 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1229#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1231#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1233#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1235#elif \
1236 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1237 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1238 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1239 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1240 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1241 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1242 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1243 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1244 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1245 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1246 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1249 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1251 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1252#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1254#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1255 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1256#else
1257 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1258#endif
1259 
1260#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1261 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1262#endif
1263#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1265#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1267#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1269#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1271#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1273#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1275#elif \
1276 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1277 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1278 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1279 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1281#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1283#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1285#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1287#else
1288 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1289#endif
1290 
1291#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1292 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1293#endif
1294#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1296#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1298#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1300#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1301 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1302#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1303 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1304#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1306#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1308#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1310#elif \
1311 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1312 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1313 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1314 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1315#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1317#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1319#else
1320 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1321#endif
1322 
1323#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1324 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1325#endif
1326#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1327 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1328#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1330#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1331 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1332#else
1333 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1334#endif
1335 
1336#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1337 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1338#endif
1339#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1340 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1341#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1343#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1344 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1345#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1346 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1347#else
1348 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1349#endif
1350 
1351#if defined(JSON_HEDLEY_DEPRECATED)
1352 #undef JSON_HEDLEY_DEPRECATED
1353#endif
1354#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1355 #undef JSON_HEDLEY_DEPRECATED_FOR
1356#endif
1357#if \
1358 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1359 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1360 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1361 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1362#elif \
1363 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1364 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1365 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1366 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1367 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1368 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1369 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1370 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1371 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1372 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1373 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1374 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1375 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1377#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1378 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1379 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1380#elif \
1381 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1382 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1383 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1384 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1385 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1386 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1387 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1388 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1389 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1390 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1391 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1392 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1393 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1394 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1395 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1396 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1397 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1398 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1399#elif \
1400 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1401 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1402 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1405#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1406 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1408#else
1409 #define JSON_HEDLEY_DEPRECATED(since)
1410 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1411#endif
1412 
1413#if defined(JSON_HEDLEY_UNAVAILABLE)
1414 #undef JSON_HEDLEY_UNAVAILABLE
1415#endif
1416#if \
1417 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1418 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1419 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1420 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1421 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1422#else
1423 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1424#endif
1425 
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1428#endif
1429#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1430 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1431#endif
1432#if \
1433 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1434 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1435 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1436 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1437 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1439 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1441 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1443 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1444 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1445 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1446 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1447 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1448 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1449 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1452#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1455#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1458#elif defined(_Check_return_) /* SAL */
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1461#else
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1463 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1464#endif
1465 
1466#if defined(JSON_HEDLEY_SENTINEL)
1467 #undef JSON_HEDLEY_SENTINEL
1468#endif
1469#if \
1470 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1471 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1474 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1475 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1476#else
1477 #define JSON_HEDLEY_SENTINEL(position)
1478#endif
1479 
1480#if defined(JSON_HEDLEY_NO_RETURN)
1481 #undef JSON_HEDLEY_NO_RETURN
1482#endif
1483#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1484 #define JSON_HEDLEY_NO_RETURN __noreturn
1485#elif \
1486 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1487 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1488 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1489#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1490 #define JSON_HEDLEY_NO_RETURN _Noreturn
1491#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1492 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1493#elif \
1494 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1495 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1496 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1497 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1498 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1499 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1500 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1501 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1502 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1503 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1504 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1505 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1506 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1507 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1508 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1509 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1510 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1511 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1512#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1513 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1514#elif \
1515 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1516 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1517 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1518#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1519 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1520#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1521 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1522#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1523 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1524#else
1525 #define JSON_HEDLEY_NO_RETURN
1526#endif
1527 
1528#if defined(JSON_HEDLEY_NO_ESCAPE)
1529 #undef JSON_HEDLEY_NO_ESCAPE
1530#endif
1531#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1532 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1533#else
1534 #define JSON_HEDLEY_NO_ESCAPE
1535#endif
1536 
1537#if defined(JSON_HEDLEY_UNREACHABLE)
1538 #undef JSON_HEDLEY_UNREACHABLE
1539#endif
1540#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1541 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1542#endif
1543#if defined(JSON_HEDLEY_ASSUME)
1544 #undef JSON_HEDLEY_ASSUME
1545#endif
1546#if \
1547 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1548 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1549 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1550 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1551#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1552 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1553#elif \
1554 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1555 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1556 #if defined(__cplusplus)
1557 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1558 #else
1559 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1560 #endif
1561#endif
1562#if \
1563 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1564 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1565 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1566 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1567 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1568 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1569 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1570 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1571#elif defined(JSON_HEDLEY_ASSUME)
1572 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1573#endif
1574#if !defined(JSON_HEDLEY_ASSUME)
1575 #if defined(JSON_HEDLEY_UNREACHABLE)
1576 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1577 #else
1578 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1579 #endif
1580#endif
1581#if defined(JSON_HEDLEY_UNREACHABLE)
1582 #if \
1583 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1584 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1585 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1586 #else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1588 #endif
1589#else
1590 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1591#endif
1592#if !defined(JSON_HEDLEY_UNREACHABLE)
1593 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1594#endif
1595 
1596JSON_HEDLEY_DIAGNOSTIC_PUSH
1597#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1598 #pragma clang diagnostic ignored "-Wpedantic"
1599#endif
1600#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1601 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1602#endif
1603#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1604 #if defined(__clang__)
1605 #pragma clang diagnostic ignored "-Wvariadic-macros"
1606 #elif defined(JSON_HEDLEY_GCC_VERSION)
1607 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1608 #endif
1609#endif
1610#if defined(JSON_HEDLEY_NON_NULL)
1611 #undef JSON_HEDLEY_NON_NULL
1612#endif
1613#if \
1614 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1615 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1616 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1617 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1618 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1619#else
1620 #define JSON_HEDLEY_NON_NULL(...)
1621#endif
1622JSON_HEDLEY_DIAGNOSTIC_POP
1623 
1624#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1625 #undef JSON_HEDLEY_PRINTF_FORMAT
1626#endif
1627#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1628 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1629#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1630 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1631#elif \
1632 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1633 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1634 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1635 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1636 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1637 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1638 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1639 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1640 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1641 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1642 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1643 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1644 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1645 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1646 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1647 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1648 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1649 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1650#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1651 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1652#else
1653 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1654#endif
1655 
1656#if defined(JSON_HEDLEY_CONSTEXPR)
1657 #undef JSON_HEDLEY_CONSTEXPR
1658#endif
1659#if defined(__cplusplus)
1660 #if __cplusplus >= 201103L
1661 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1662 #endif
1663#endif
1664#if !defined(JSON_HEDLEY_CONSTEXPR)
1665 #define JSON_HEDLEY_CONSTEXPR
1666#endif
1667 
1668#if defined(JSON_HEDLEY_PREDICT)
1669 #undef JSON_HEDLEY_PREDICT
1670#endif
1671#if defined(JSON_HEDLEY_LIKELY)
1672 #undef JSON_HEDLEY_LIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNLIKELY)
1675 #undef JSON_HEDLEY_UNLIKELY
1676#endif
1677#if defined(JSON_HEDLEY_UNPREDICTABLE)
1678 #undef JSON_HEDLEY_UNPREDICTABLE
1679#endif
1680#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1681 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1682#endif
1683#if \
1684 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1685 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1686 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1687# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1688# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1689# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1690# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1691# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1692#elif \
1693 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1694 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1695 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1696 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1697 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1698 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1699 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1700 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1701 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1702 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1703 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1704 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1705 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1706 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1707 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1708 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1709# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1710 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1711# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1712 (__extension__ ({ \
1713 double hedley_probability_ = (probability); \
1714 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1715 }))
1716# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1717 (__extension__ ({ \
1718 double hedley_probability_ = (probability); \
1719 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1720 }))
1721# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1722# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1723#else
1724# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1725# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1726# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1727# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1728# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1729#endif
1730#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1731 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1732#endif
1733 
1734#if defined(JSON_HEDLEY_MALLOC)
1735 #undef JSON_HEDLEY_MALLOC
1736#endif
1737#if \
1738 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1739 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1740 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1741 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1742 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1743 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1744 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1745 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1746 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1747 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1748 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1749 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1750 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1751 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1752 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1753 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1754 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1755 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1756 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1757#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1758 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1759#elif \
1760 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1761 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1762 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1763#else
1764 #define JSON_HEDLEY_MALLOC
1765#endif
1766 
1767#if defined(JSON_HEDLEY_PURE)
1768 #undef JSON_HEDLEY_PURE
1769#endif
1770#if \
1771 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1772 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1773 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1774 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1775 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1776 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1777 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1778 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1779 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1780 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1781 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1782 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1783 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1784 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1785 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1786 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1787 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1788 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1789 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1790# define JSON_HEDLEY_PURE __attribute__((__pure__))
1791#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1792# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1793#elif defined(__cplusplus) && \
1794 ( \
1795 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1796 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1797 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1798 )
1799# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1800#else
1801# define JSON_HEDLEY_PURE
1802#endif
1803 
1804#if defined(JSON_HEDLEY_CONST)
1805 #undef JSON_HEDLEY_CONST
1806#endif
1807#if \
1808 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1809 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1810 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1811 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1812 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1813 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1814 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1815 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1816 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1817 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1818 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1819 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1820 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1821 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1822 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1823 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1824 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1825 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1826 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1827 #define JSON_HEDLEY_CONST __attribute__((__const__))
1828#elif \
1829 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1830 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1831#else
1832 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1833#endif
1834 
1835#if defined(JSON_HEDLEY_RESTRICT)
1836 #undef JSON_HEDLEY_RESTRICT
1837#endif
1838#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1839 #define JSON_HEDLEY_RESTRICT restrict
1840#elif \
1841 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1842 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1843 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1844 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1845 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1846 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1847 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1848 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1849 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1850 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1851 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1852 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1853 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1854 defined(__clang__) || \
1855 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1856 #define JSON_HEDLEY_RESTRICT __restrict
1857#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1858 #define JSON_HEDLEY_RESTRICT _Restrict
1859#else
1860 #define JSON_HEDLEY_RESTRICT
1861#endif
1862 
1863#if defined(JSON_HEDLEY_INLINE)
1864 #undef JSON_HEDLEY_INLINE
1865#endif
1866#if \
1867 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1868 (defined(__cplusplus) && (__cplusplus >= 199711L))
1869 #define JSON_HEDLEY_INLINE inline
1870#elif \
1871 defined(JSON_HEDLEY_GCC_VERSION) || \
1872 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1873 #define JSON_HEDLEY_INLINE __inline__
1874#elif \
1875 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1876 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1877 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1878 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1879 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1880 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1881 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1882 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1883 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1884 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1885 #define JSON_HEDLEY_INLINE __inline
1886#else
1887 #define JSON_HEDLEY_INLINE
1888#endif
1889 
1890#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1891 #undef JSON_HEDLEY_ALWAYS_INLINE
1892#endif
1893#if \
1894 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1895 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1896 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1897 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1898 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1899 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1900 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1901 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1902 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1903 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1904 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1905 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1906 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1907 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1908 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1909 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1910 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1911 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1912 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1913# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1914#elif \
1915 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1916 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1917# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1918#elif defined(__cplusplus) && \
1919 ( \
1920 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1921 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1922 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1923 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1924 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1925 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1926 )
1927# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1928#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1929# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1930#else
1931# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1932#endif
1933 
1934#if defined(JSON_HEDLEY_NEVER_INLINE)
1935 #undef JSON_HEDLEY_NEVER_INLINE
1936#endif
1937#if \
1938 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1939 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1940 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1941 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1942 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1943 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1944 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1945 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1946 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1947 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1948 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1949 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1950 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1951 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1952 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1953 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1954 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1955 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1956 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1957 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1958#elif \
1959 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1960 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1963 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1964#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1965 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1966#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1967 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1968#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1969 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1970#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1971 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1972#else
1973 #define JSON_HEDLEY_NEVER_INLINE
1974#endif
1975 
1976#if defined(JSON_HEDLEY_PRIVATE)
1977 #undef JSON_HEDLEY_PRIVATE
1978#endif
1979#if defined(JSON_HEDLEY_PUBLIC)
1980 #undef JSON_HEDLEY_PUBLIC
1981#endif
1982#if defined(JSON_HEDLEY_IMPORT)
1983 #undef JSON_HEDLEY_IMPORT
1984#endif
1985#if defined(_WIN32) || defined(__CYGWIN__)
1986# define JSON_HEDLEY_PRIVATE
1987# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1988# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1989#else
1990# if \
1991 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1992 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1993 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1994 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1995 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1996 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1997 ( \
1998 defined(__TI_EABI__) && \
1999 ( \
2000 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2001 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2002 ) \
2003 ) || \
2004 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2005# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2006# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2007# else
2008# define JSON_HEDLEY_PRIVATE
2009# define JSON_HEDLEY_PUBLIC
2010# endif
2011# define JSON_HEDLEY_IMPORT extern
2012#endif
2013 
2014#if defined(JSON_HEDLEY_NO_THROW)
2015 #undef JSON_HEDLEY_NO_THROW
2016#endif
2017#if \
2018 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2019 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2020 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2021 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2022 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2023#elif \
2024 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2025 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2026 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2027 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2028#else
2029 #define JSON_HEDLEY_NO_THROW
2030#endif
2031 
2032#if defined(JSON_HEDLEY_FALL_THROUGH)
2033 #undef JSON_HEDLEY_FALL_THROUGH
2034#endif
2035#if \
2036 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2037 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2038 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2039 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2041 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2043 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2044#elif defined(__fallthrough) /* SAL */
2045 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2046#else
2047 #define JSON_HEDLEY_FALL_THROUGH
2048#endif
2049 
2050#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2051 #undef JSON_HEDLEY_RETURNS_NON_NULL
2052#endif
2053#if \
2054 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2055 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2056 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2057 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2058#elif defined(_Ret_notnull_) /* SAL */
2059 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2060#else
2061 #define JSON_HEDLEY_RETURNS_NON_NULL
2062#endif
2063 
2064#if defined(JSON_HEDLEY_ARRAY_PARAM)
2065 #undef JSON_HEDLEY_ARRAY_PARAM
2066#endif
2067#if \
2068 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2069 !defined(__STDC_NO_VLA__) && \
2070 !defined(__cplusplus) && \
2071 !defined(JSON_HEDLEY_PGI_VERSION) && \
2072 !defined(JSON_HEDLEY_TINYC_VERSION)
2073 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2074#else
2075 #define JSON_HEDLEY_ARRAY_PARAM(name)
2076#endif
2077 
2078#if defined(JSON_HEDLEY_IS_CONSTANT)
2079 #undef JSON_HEDLEY_IS_CONSTANT
2080#endif
2081#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2082 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2083#endif
2084/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2085 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2086#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2087 #undef JSON_HEDLEY_IS_CONSTEXPR_
2088#endif
2089#if \
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2094 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2095 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2096 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2097 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2099 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2100 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2101#endif
2102#if !defined(__cplusplus)
2103# if \
2104 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2105 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2106 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2107 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2108 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2109 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2110 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2111#if defined(__INTPTR_TYPE__)
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2113#else
2114 #include <stdint.h>
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2116#endif
2117# elif \
2118 ( \
2119 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2120 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2121 !defined(JSON_HEDLEY_PGI_VERSION) && \
2122 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2123 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2124 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2125 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2126 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2127 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2128#if defined(__INTPTR_TYPE__)
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2130#else
2131 #include <stdint.h>
2132 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2133#endif
2134# elif \
2135 defined(JSON_HEDLEY_GCC_VERSION) || \
2136 defined(JSON_HEDLEY_INTEL_VERSION) || \
2137 defined(JSON_HEDLEY_TINYC_VERSION) || \
2138 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2139 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2140 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2141 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2142 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2143 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2144 defined(__clang__)
2145# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2146 sizeof(void) != \
2147 sizeof(*( \
2148 1 ? \
2149 ((void*) ((expr) * 0L) ) : \
2150((struct { char v[sizeof(void) * 2]; } *) 1) \
2151 ) \
2152 ) \
2153 )
2154# endif
2155#endif
2156#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2157 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2158 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2159 #endif
2160 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2161#else
2162 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2163 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2164 #endif
2165 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2166#endif
2167 
2168#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2169 #undef JSON_HEDLEY_BEGIN_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_END_C_DECLS)
2172 #undef JSON_HEDLEY_END_C_DECLS
2173#endif
2174#if defined(JSON_HEDLEY_C_DECL)
2175 #undef JSON_HEDLEY_C_DECL
2176#endif
2177#if defined(__cplusplus)
2178 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2179 #define JSON_HEDLEY_END_C_DECLS }
2180 #define JSON_HEDLEY_C_DECL extern "C"
2181#else
2182 #define JSON_HEDLEY_BEGIN_C_DECLS
2183 #define JSON_HEDLEY_END_C_DECLS
2184 #define JSON_HEDLEY_C_DECL
2185#endif
2186 
2187#if defined(JSON_HEDLEY_STATIC_ASSERT)
2188 #undef JSON_HEDLEY_STATIC_ASSERT
2189#endif
2190#if \
2191 !defined(__cplusplus) && ( \
2192 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2193 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2194 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2195 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2196 defined(_Static_assert) \
2197 )
2198# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2199#elif \
2200 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2201 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2202 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2203# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2204#else
2205# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2206#endif
2207 
2208#if defined(JSON_HEDLEY_NULL)
2209 #undef JSON_HEDLEY_NULL
2210#endif
2211#if defined(__cplusplus)
2212 #if __cplusplus >= 201103L
2213 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2214 #elif defined(NULL)
2215 #define JSON_HEDLEY_NULL NULL
2216 #else
2217 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2218 #endif
2219#elif defined(NULL)
2220 #define JSON_HEDLEY_NULL NULL
2221#else
2222 #define JSON_HEDLEY_NULL ((void*) 0)
2223#endif
2224 
2225#if defined(JSON_HEDLEY_MESSAGE)
2226 #undef JSON_HEDLEY_MESSAGE
2227#endif
2228#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2229# define JSON_HEDLEY_MESSAGE(msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2231 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2232 JSON_HEDLEY_PRAGMA(message msg) \
2233 JSON_HEDLEY_DIAGNOSTIC_POP
2234#elif \
2235 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2236 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2237# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2238#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2239# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2240#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2241# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2242#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2243# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2244#else
2245# define JSON_HEDLEY_MESSAGE(msg)
2246#endif
2247 
2248#if defined(JSON_HEDLEY_WARNING)
2249 #undef JSON_HEDLEY_WARNING
2250#endif
2251#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2252# define JSON_HEDLEY_WARNING(msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2254 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2255 JSON_HEDLEY_PRAGMA(clang warning msg) \
2256 JSON_HEDLEY_DIAGNOSTIC_POP
2257#elif \
2258 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2259 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2260 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2261# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2262#elif \
2263 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2264 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2265# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2266#else
2267# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2268#endif
2269 
2270#if defined(JSON_HEDLEY_REQUIRE)
2271 #undef JSON_HEDLEY_REQUIRE
2272#endif
2273#if defined(JSON_HEDLEY_REQUIRE_MSG)
2274 #undef JSON_HEDLEY_REQUIRE_MSG
2275#endif
2276#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2277# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2278# define JSON_HEDLEY_REQUIRE(expr) \
2279 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2280 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2281 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2282 JSON_HEDLEY_DIAGNOSTIC_POP
2283# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2284 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2285 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2286 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2287 JSON_HEDLEY_DIAGNOSTIC_POP
2288# else
2289# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2290# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2291# endif
2292#else
2293# define JSON_HEDLEY_REQUIRE(expr)
2294# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2295#endif
2296 
2297#if defined(JSON_HEDLEY_FLAGS)
2298 #undef JSON_HEDLEY_FLAGS
2299#endif
2300#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2301 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2302#else
2303 #define JSON_HEDLEY_FLAGS
2304#endif
2305 
2306#if defined(JSON_HEDLEY_FLAGS_CAST)
2307 #undef JSON_HEDLEY_FLAGS_CAST
2308#endif
2309#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2310# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2311 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2312 _Pragma("warning(disable:188)") \
2313 ((T) (expr)); \
2314 JSON_HEDLEY_DIAGNOSTIC_POP \
2315 }))
2316#else
2317# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2318#endif
2319 
2320#if defined(JSON_HEDLEY_EMPTY_BASES)
2321 #undef JSON_HEDLEY_EMPTY_BASES
2322#endif
2323#if \
2324 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2325 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2326 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2327#else
2328 #define JSON_HEDLEY_EMPTY_BASES
2329#endif
2330 
2331/* Remaining macros are deprecated. */
2332 
2333#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2334 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2335#endif
2336#if defined(__clang__)
2337 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2338#else
2339 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2340#endif
2341 
2342#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2343 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2344#endif
2345#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2346 
2347#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2348 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2349#endif
2350#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2351 
2352#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2353 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2356 
2357#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2358 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2361 
2362#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2363 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2366 
2367#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2368 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2369#endif
2370#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2371 
2372#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2373 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2374#endif
2375#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2376 
2377#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2378 
2379 
2380// This file contains all internal macro definitions (except those affecting ABI)
2381// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2382 
2383// #include <nlohmann/detail/abi_macros.hpp>
2384 
2385 
2386// exclude unsupported compilers
2387#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2388 #if defined(__clang__)
2389 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2390 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2391 #endif
2392 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2393 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2394 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2395 #endif
2396 #endif
2397#endif
2398 
2399// C++ language standard detection
2400// if the user manually specified the used c++ version this is skipped
2401#if !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2402 #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2403 #define JSON_HAS_CPP_23
2404 #define JSON_HAS_CPP_20
2405 #define JSON_HAS_CPP_17
2406 #define JSON_HAS_CPP_14
2407 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2408 #define JSON_HAS_CPP_20
2409 #define JSON_HAS_CPP_17
2410 #define JSON_HAS_CPP_14
2411 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2412 #define JSON_HAS_CPP_17
2413 #define JSON_HAS_CPP_14
2414 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2415 #define JSON_HAS_CPP_14
2416 #endif
2417 // the cpp 11 flag is always specified because it is the minimal required version
2418 #define JSON_HAS_CPP_11
2419#endif
2420 
2421#ifdef __has_include
2422 #if __has_include(<version>)
2423 #include <version>
2424 #endif
2425#endif
2426 
2427#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2428 #ifdef JSON_HAS_CPP_17
2429 #if defined(__cpp_lib_filesystem)
2430 #define JSON_HAS_FILESYSTEM 1
2431 #elif defined(__cpp_lib_experimental_filesystem)
2432 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2433 #elif !defined(__has_include)
2434 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2435 #elif __has_include(<filesystem>)
2436 #define JSON_HAS_FILESYSTEM 1
2437 #elif __has_include(<experimental/filesystem>)
2438 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2439 #endif
2440 
2441 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2442 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2443 #undef JSON_HAS_FILESYSTEM
2444 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2445 #endif
2446 
2447 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2448 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2449 #undef JSON_HAS_FILESYSTEM
2450 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2451 #endif
2452 
2453 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2454 #if defined(__clang_major__) && __clang_major__ < 7
2455 #undef JSON_HAS_FILESYSTEM
2456 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2457 #endif
2458 
2459 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2460 #if defined(_MSC_VER) && _MSC_VER < 1914
2461 #undef JSON_HAS_FILESYSTEM
2462 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2463 #endif
2464 
2465 // no filesystem support before iOS 13
2466 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2467 #undef JSON_HAS_FILESYSTEM
2468 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2469 #endif
2470 
2471 // no filesystem support before macOS Catalina
2472 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2473 #undef JSON_HAS_FILESYSTEM
2474 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2475 #endif
2476 #endif
2477#endif
2478 
2479#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2480 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2481#endif
2482 
2483#ifndef JSON_HAS_FILESYSTEM
2484 #define JSON_HAS_FILESYSTEM 0
2485#endif
2486 
2487#ifndef JSON_HAS_THREE_WAY_COMPARISON
2488 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2489 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2490 #define JSON_HAS_THREE_WAY_COMPARISON 1
2491 #else
2492 #define JSON_HAS_THREE_WAY_COMPARISON 0
2493 #endif
2494#endif
2495 
2496#ifndef JSON_HAS_RANGES
2497 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2498 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2499 #define JSON_HAS_RANGES 0
2500 #elif defined(__cpp_lib_ranges)
2501 #define JSON_HAS_RANGES 1
2502 #else
2503 #define JSON_HAS_RANGES 0
2504 #endif
2505#endif
2506 
2507#ifndef JSON_HAS_STATIC_RTTI
2508 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2509 #define JSON_HAS_STATIC_RTTI 1
2510 #else
2511 #define JSON_HAS_STATIC_RTTI 0
2512 #endif
2513#endif
2514 
2515#ifdef JSON_HAS_CPP_17
2516 #define JSON_INLINE_VARIABLE inline
2517#else
2518 #define JSON_INLINE_VARIABLE
2519#endif
2520 
2521#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2522 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2523#else
2524 #define JSON_NO_UNIQUE_ADDRESS
2525#endif
2526 
2527// disable documentation warnings on clang
2528#if defined(__clang__)
2529 #pragma clang diagnostic push
2530 #pragma clang diagnostic ignored "-Wdocumentation"
2531 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2532#endif
2533 
2534// allow disabling exceptions
2535#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2536 #define JSON_THROW(exception) throw exception
2537 #define JSON_TRY try
2538 #define JSON_CATCH(exception) catch(exception)
2539 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2540#else
2541 #include <cstdlib>
2542 #define JSON_THROW(exception) std::abort()
2543 #define JSON_TRY if(true)
2544 #define JSON_CATCH(exception) if(false)
2545 #define JSON_INTERNAL_CATCH(exception) if(false)
2546#endif
2547 
2548// override exception macros
2549#if defined(JSON_THROW_USER)
2550 #undef JSON_THROW
2551 #define JSON_THROW JSON_THROW_USER
2552#endif
2553#if defined(JSON_TRY_USER)
2554 #undef JSON_TRY
2555 #define JSON_TRY JSON_TRY_USER
2556#endif
2557#if defined(JSON_CATCH_USER)
2558 #undef JSON_CATCH
2559 #define JSON_CATCH JSON_CATCH_USER
2560 #undef JSON_INTERNAL_CATCH
2561 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2562#endif
2563#if defined(JSON_INTERNAL_CATCH_USER)
2564 #undef JSON_INTERNAL_CATCH
2565 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2566#endif
2567 
2568// allow overriding assert
2569#if !defined(JSON_ASSERT)
2570 #include <cassert> // assert
2571 #define JSON_ASSERT(x) assert(x)
2572#endif
2573 
2574// allow to access some private functions (needed by the test suite)
2575#if defined(JSON_TESTS_PRIVATE)
2576 #define JSON_PRIVATE_UNLESS_TESTED public
2577#else
2578 #define JSON_PRIVATE_UNLESS_TESTED private
2579#endif
2580 
2581/*!
2582@brief macro to briefly define a mapping between an enum and JSON
2583@def NLOHMANN_JSON_SERIALIZE_ENUM
2584@since version 3.4.0
2585*/
2586#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2587 template<typename BasicJsonType> \
2588 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2589 { \
2590 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2591 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2592 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2593 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2594 auto it = std::find_if(std::begin(m), std::end(m), \
2595 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2596 { \
2597 return ej_pair.first == e; \
2598 }); \
2599 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2600 } \
2601 template<typename BasicJsonType> \
2602 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2603 { \
2604 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2605 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2606 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2607 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2608 auto it = std::find_if(std::begin(m), std::end(m), \
2609 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2610 { \
2611 return ej_pair.second == j; \
2612 }); \
2613 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2614 }
2615 
2616// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2617// may be removed in the future once the class is split.
2618 
2619#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2620 template<template<typename, typename, typename...> class ObjectType, \
2621 template<typename, typename...> class ArrayType, \
2622 class StringType, class BooleanType, class NumberIntegerType, \
2623 class NumberUnsignedType, class NumberFloatType, \
2624 template<typename> class AllocatorType, \
2625 template<typename, typename = void> class JSONSerializer, \
2626 class BinaryType, \
2627 class CustomBaseClass>
2628 
2629#define NLOHMANN_BASIC_JSON_TPL \
2630 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2631 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2632 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2633 
2634// Macros to simplify conversion from/to types
2635 
2636#define NLOHMANN_JSON_EXPAND( x ) x
2637#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
2638#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2639 NLOHMANN_JSON_PASTE64, \
2640 NLOHMANN_JSON_PASTE63, \
2641 NLOHMANN_JSON_PASTE62, \
2642 NLOHMANN_JSON_PASTE61, \
2643 NLOHMANN_JSON_PASTE60, \
2644 NLOHMANN_JSON_PASTE59, \
2645 NLOHMANN_JSON_PASTE58, \
2646 NLOHMANN_JSON_PASTE57, \
2647 NLOHMANN_JSON_PASTE56, \
2648 NLOHMANN_JSON_PASTE55, \
2649 NLOHMANN_JSON_PASTE54, \
2650 NLOHMANN_JSON_PASTE53, \
2651 NLOHMANN_JSON_PASTE52, \
2652 NLOHMANN_JSON_PASTE51, \
2653 NLOHMANN_JSON_PASTE50, \
2654 NLOHMANN_JSON_PASTE49, \
2655 NLOHMANN_JSON_PASTE48, \
2656 NLOHMANN_JSON_PASTE47, \
2657 NLOHMANN_JSON_PASTE46, \
2658 NLOHMANN_JSON_PASTE45, \
2659 NLOHMANN_JSON_PASTE44, \
2660 NLOHMANN_JSON_PASTE43, \
2661 NLOHMANN_JSON_PASTE42, \
2662 NLOHMANN_JSON_PASTE41, \
2663 NLOHMANN_JSON_PASTE40, \
2664 NLOHMANN_JSON_PASTE39, \
2665 NLOHMANN_JSON_PASTE38, \
2666 NLOHMANN_JSON_PASTE37, \
2667 NLOHMANN_JSON_PASTE36, \
2668 NLOHMANN_JSON_PASTE35, \
2669 NLOHMANN_JSON_PASTE34, \
2670 NLOHMANN_JSON_PASTE33, \
2671 NLOHMANN_JSON_PASTE32, \
2672 NLOHMANN_JSON_PASTE31, \
2673 NLOHMANN_JSON_PASTE30, \
2674 NLOHMANN_JSON_PASTE29, \
2675 NLOHMANN_JSON_PASTE28, \
2676 NLOHMANN_JSON_PASTE27, \
2677 NLOHMANN_JSON_PASTE26, \
2678 NLOHMANN_JSON_PASTE25, \
2679 NLOHMANN_JSON_PASTE24, \
2680 NLOHMANN_JSON_PASTE23, \
2681 NLOHMANN_JSON_PASTE22, \
2682 NLOHMANN_JSON_PASTE21, \
2683 NLOHMANN_JSON_PASTE20, \
2684 NLOHMANN_JSON_PASTE19, \
2685 NLOHMANN_JSON_PASTE18, \
2686 NLOHMANN_JSON_PASTE17, \
2687 NLOHMANN_JSON_PASTE16, \
2688 NLOHMANN_JSON_PASTE15, \
2689 NLOHMANN_JSON_PASTE14, \
2690 NLOHMANN_JSON_PASTE13, \
2691 NLOHMANN_JSON_PASTE12, \
2692 NLOHMANN_JSON_PASTE11, \
2693 NLOHMANN_JSON_PASTE10, \
2694 NLOHMANN_JSON_PASTE9, \
2695 NLOHMANN_JSON_PASTE8, \
2696 NLOHMANN_JSON_PASTE7, \
2697 NLOHMANN_JSON_PASTE6, \
2698 NLOHMANN_JSON_PASTE5, \
2699 NLOHMANN_JSON_PASTE4, \
2700 NLOHMANN_JSON_PASTE3, \
2701 NLOHMANN_JSON_PASTE2, \
2702 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2703#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2704#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2705#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2706#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2707#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764#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)
2765#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)
2766 
2767#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2768#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2769#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1;
2770 
2771/*!
2772@brief macro
2773@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
2774@since version 3.9.0
2775@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2776*/
2777#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2778 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2779 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2780 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2781 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2782 
2783/*!
2784@brief macro
2785@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
2786@since version 3.11.0
2787@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2788*/
2789#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2790 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2791 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2792 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2793 friend void from_json(const BasicJsonType& 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__)) }
2794 
2795/*!
2796@brief macro
2797@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE
2798@since version 3.11.3
2799@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
2800*/
2801#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2802 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2803 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2804 
2805/*!
2806@brief macro
2807@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
2808@since version 3.9.0
2809@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2810*/
2811#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2812 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2813 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2814 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2815 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2816 
2817/*!
2818@brief macro
2819@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
2820@since version 3.11.0
2821@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2822*/
2823#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2824 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2825 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2826 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2827 void from_json(const BasicJsonType& 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__)) }
2828 
2829/*!
2830@brief macro
2831@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
2832@since version 3.11.3
2833@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
2834*/
2835#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2836 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2837 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2838 
2839/*!
2840@brief macro
2841@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE
2842@since version 3.12.0
2843@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2844*/
2845#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2846 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2847 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2848 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2849 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2850 
2851/*!
2852@brief macro
2853@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
2854@since version 3.12.0
2855@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2856*/
2857#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2858 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2859 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2860 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2861 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2862 
2863/*!
2864@brief macro
2865@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE
2866@since version 3.12.0
2867@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2868*/
2869#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2870 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2871 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2872 
2873/*!
2874@brief macro
2875@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE
2876@since version 3.12.0
2877@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2878*/
2879#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2880 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2881 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2882 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2883 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2884 
2885/*!
2886@brief macro
2887@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
2888@since version 3.12.0
2889@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2890*/
2891#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2892 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2893 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2894 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2895 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2896 
2897/*!
2898@brief macro
2899@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
2900@since version 3.12.0
2901@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
2902*/
2903#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2904 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2905 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2906 
2907// inspired from https://stackoverflow.com/a/26745591
2908// allows calling any std function as if (e.g., with begin):
2909// using std::begin; begin(x);
2910//
2911// it allows using the detected idiom to retrieve the return type
2912// of such an expression
2913#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2914 namespace detail { \
2915 using std::std_name; \
2916 \
2917 template<typename... T> \
2918 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2919 } \
2920 \
2921 namespace detail2 { \
2922 struct std_name##_tag \
2923 { \
2924 }; \
2925 \
2926 template<typename... T> \
2927 std_name##_tag std_name(T&&...); \
2928 \
2929 template<typename... T> \
2930 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2931 \
2932 template<typename... T> \
2933 struct would_call_std_##std_name \
2934 { \
2935 static constexpr auto const value = ::nlohmann::detail:: \
2936 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2937 }; \
2938 } /* namespace detail2 */ \
2939 \
2940 template<typename... T> \
2941 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2942 { \
2943 }
2944 
2945#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2946 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2947#endif
2948 
2949#if JSON_USE_IMPLICIT_CONVERSIONS
2950 #define JSON_EXPLICIT
2951#else
2952 #define JSON_EXPLICIT explicit
2953#endif
2954 
2955#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2956 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2957#endif
2958 
2959#ifndef JSON_USE_GLOBAL_UDLS
2960 #define JSON_USE_GLOBAL_UDLS 1
2961#endif
2962 
2963#if JSON_HAS_THREE_WAY_COMPARISON
2964 #include <compare> // partial_ordering
2965#endif
2966 
2967NLOHMANN_JSON_NAMESPACE_BEGIN
2968namespace detail
2969{
2970 
2971///////////////////////////
2972// JSON type enumeration //
2973///////////////////////////
2974 
2975/*!
2976@brief the JSON type enumeration
2977 
2978This enumeration collects the different JSON types. It is internally used to
2979distinguish the stored values, and the functions @ref basic_json::is_null(),
2980@ref basic_json::is_object(), @ref basic_json::is_array(),
2981@ref basic_json::is_string(), @ref basic_json::is_boolean(),
2982@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
2983@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
2984@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
2985@ref basic_json::is_structured() rely on it.
2986 
2987@note There are three enumeration entries (number_integer, number_unsigned, and
2988number_float), because the library distinguishes these three types for numbers:
2989@ref basic_json::number_unsigned_t is used for unsigned integers,
2990@ref basic_json::number_integer_t is used for signed integers, and
2991@ref basic_json::number_float_t is used for floating-point numbers or to
2992approximate integers which do not fit in the limits of their respective type.
2993 
2994@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
2995value with the default value for a given type
2996 
2997@since version 1.0.0
2998*/
2999enum class value_t : std::uint8_t
3000{
3001 null, ///< null value
3002 object, ///< object (unordered set of name/value pairs)
3003 array, ///< array (ordered collection of values)
3004 string, ///< string value
3005 boolean, ///< boolean value
3006 number_integer, ///< number value (signed integer)
3007 number_unsigned, ///< number value (unsigned integer)
3008 number_float, ///< number value (floating-point)
3009 binary, ///< binary array (ordered collection of bytes)
3010 discarded ///< discarded by the parser callback function
3011};
3012 
3013/*!
3014@brief comparison operator for JSON types
3015 
3016Returns an ordering that is similar to Python:
3017- order: null < boolean < number < object < array < string < binary
3018- furthermore, each type is not smaller than itself
3019- discarded values are not comparable
3020- binary is represented as a b"" string in python and directly comparable to a
3021 string; however, making a binary array directly comparable with a string would
3022 be surprising behavior in a JSON file.
3023 
3024@since version 1.0.0
3025*/
3026#if JSON_HAS_THREE_WAY_COMPARISON
3027 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3028#else
3029 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3030#endif
3031{
3032 static constexpr std::array<std::uint8_t, 9> order = {{
3033 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3034 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3035 6 /* binary */
3036 }
3037 };
3038 
3039 const auto l_index = static_cast<std::size_t>(lhs);
3040 const auto r_index = static_cast<std::size_t>(rhs);
3041#if JSON_HAS_THREE_WAY_COMPARISON
3042 if (l_index < order.size() && r_index < order.size())
3043 {
3044 return order[l_index] <=> order[r_index]; // *NOPAD*
3045 }
3046 return std::partial_ordering::unordered;
3047#else
3048 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3049#endif
3050}
3051 
3052// GCC selects the built-in operator< over an operator rewritten from
3053// a user-defined spaceship operator
3054// Clang, MSVC, and ICC select the rewritten candidate
3055// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3056#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3057inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3058{
3059 return std::is_lt(lhs <=> rhs); // *NOPAD*
3060}
3061#endif
3062 
3063} // namespace detail
3064NLOHMANN_JSON_NAMESPACE_END
3065 
3066// #include <nlohmann/detail/string_escape.hpp>
3067// __ _____ _____ _____
3068// __| | __| | | | JSON for Modern C++
3069// | | |__ | | | | | | version 3.12.0
3070// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3071//
3072// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3073// SPDX-License-Identifier: MIT
3074 
3075 
3076 
3077// #include <nlohmann/detail/abi_macros.hpp>
3078 
3079 
3080NLOHMANN_JSON_NAMESPACE_BEGIN
3081namespace detail
3082{
3083 
3084/*!
3085@brief replace all occurrences of a substring by another string
3086 
3087@param[in,out] s the string to manipulate; changed so that all
3088 occurrences of @a f are replaced with @a t
3089@param[in] f the substring to replace with @a t
3090@param[in] t the string to replace @a f
3091 
3092@pre The search string @a f must not be empty. **This precondition is
3093enforced with an assertion.**
3094 
3095@since version 2.0.0
3096*/
3097template<typename StringType>
3098inline void replace_substring(StringType& s, const StringType& f,
3099 const StringType& t)
3100{
3101 JSON_ASSERT(!f.empty());
3102 for (auto pos = s.find(f); // find first occurrence of f
3103 pos != StringType::npos; // make sure f was found
3104 s.replace(pos, f.size(), t), // replace with t, and
3105 pos = s.find(f, pos + t.size())) // find next occurrence of f
3106 {}
3107}
3108 
3109/*!
3110 * @brief string escaping as described in RFC 6901 (Sect. 4)
3111 * @param[in] s string to escape
3112 * @return escaped string
3113 *
3114 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
3115 */
3116template<typename StringType>
3117inline StringType escape(StringType s)
3118{
3119 replace_substring(s, StringType{"~"}, StringType{"~0"});
3120 replace_substring(s, StringType{"/"}, StringType{"~1"});
3121 return s;
3122}
3123 
3124/*!
3125 * @brief string unescaping as described in RFC 6901 (Sect. 4)
3126 * @param[in] s string to unescape
3127 * @return unescaped string
3128 *
3129 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
3130 */
3131template<typename StringType>
3132static void unescape(StringType& s)
3133{
3134 replace_substring(s, StringType{"~1"}, StringType{"/"});
3135 replace_substring(s, StringType{"~0"}, StringType{"~"});
3136}
3137 
3138} // namespace detail
3139NLOHMANN_JSON_NAMESPACE_END
3140 
3141// #include <nlohmann/detail/input/position_t.hpp>
3142// __ _____ _____ _____
3143// __| | __| | | | JSON for Modern C++
3144// | | |__ | | | | | | version 3.12.0
3145// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3146//
3147// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3148// SPDX-License-Identifier: MIT
3149 
3150 
3151 
3152#include <cstddef> // size_t
3153 
3154// #include <nlohmann/detail/abi_macros.hpp>
3155 
3156 
3157NLOHMANN_JSON_NAMESPACE_BEGIN
3158namespace detail
3159{
3160 
3161/// struct to capture the start position of the current token
3162struct position_t
3163{
3164 /// the total number of characters read
3165 std::size_t chars_read_total = 0;
3166 /// the number of characters read in the current line
3167 std::size_t chars_read_current_line = 0;
3168 /// the number of lines read
3169 std::size_t lines_read = 0;
3170 
3171 /// conversion to size_t to preserve SAX interface
3172 constexpr operator size_t() const
3173 {
3174 return chars_read_total;
3175 }
3176};
3177 
3178} // namespace detail
3179NLOHMANN_JSON_NAMESPACE_END
3180 
3181// #include <nlohmann/detail/macro_scope.hpp>
3182 
3183// #include <nlohmann/detail/meta/cpp_future.hpp>
3184// __ _____ _____ _____
3185// __| | __| | | | JSON for Modern C++
3186// | | |__ | | | | | | version 3.12.0
3187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3188//
3189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3190// SPDX-FileCopyrightText: 2018 The Abseil Authors
3191// SPDX-License-Identifier: MIT
3192 
3193 
3194 
3195#include <array> // array
3196#include <cstddef> // size_t
3197#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3198#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3199 
3200// #include <nlohmann/detail/macro_scope.hpp>
3201 
3202 
3203NLOHMANN_JSON_NAMESPACE_BEGIN
3204namespace detail
3205{
3206 
3207template<typename T>
3208using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3209 
3210#ifdef JSON_HAS_CPP_14
3211 
3212// the following utilities are natively available in C++14
3213using std::enable_if_t;
3214using std::index_sequence;
3215using std::make_index_sequence;
3216using std::index_sequence_for;
3217 
3218#else
3219 
3220// alias templates to reduce boilerplate
3221template<bool B, typename T = void>
3222using enable_if_t = typename std::enable_if<B, T>::type;
3223 
3224// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3225// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3226 
3227//// START OF CODE FROM GOOGLE ABSEIL
3228 
3229// integer_sequence
3230//
3231// Class template representing a compile-time integer sequence. An instantiation
3232// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3233// type through its template arguments (which is a common need when
3234// working with C++11 variadic templates). `absl::integer_sequence` is designed
3235// to be a drop-in replacement for C++14's `std::integer_sequence`.
3236//
3237// Example:
3238//
3239// template< class T, T... Ints >
3240// void user_function(integer_sequence<T, Ints...>);
3241//
3242// int main()
3243// {
3244// // user_function's `T` will be deduced to `int` and `Ints...`
3245// // will be deduced to `0, 1, 2, 3, 4`.
3246// user_function(make_integer_sequence<int, 5>());
3247// }
3248template <typename T, T... Ints>
3249struct integer_sequence
3250{
3251 using value_type = T;
3252 static constexpr std::size_t size() noexcept
3253 {
3254 return sizeof...(Ints);
3255 }
3256};
3257 
3258// index_sequence
3259//
3260// A helper template for an `integer_sequence` of `size_t`,
3261// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3262// `std::index_sequence`.
3263template <size_t... Ints>
3264using index_sequence = integer_sequence<size_t, Ints...>;
3265 
3266namespace utility_internal
3267{
3268 
3269template <typename Seq, size_t SeqSize, size_t Rem>
3270struct Extend;
3271 
3272// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3273template <typename T, T... Ints, size_t SeqSize>
3274struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3275{
3276 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3277};
3278 
3279template <typename T, T... Ints, size_t SeqSize>
3280struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3281{
3282 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3283};
3284 
3285// Recursion helper for 'make_integer_sequence<T, N>'.
3286// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3287template <typename T, size_t N>
3288struct Gen
3289{
3290 using type =
3291 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3292};
3293 
3294template <typename T>
3295struct Gen<T, 0>
3296{
3297 using type = integer_sequence<T>;
3298};
3299 
3300} // namespace utility_internal
3301 
3302// Compile-time sequences of integers
3303 
3304// make_integer_sequence
3305//
3306// This template alias is equivalent to
3307// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3308// replacement for C++14's `std::make_integer_sequence`.
3309template <typename T, T N>
3310using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3311 
3312// make_index_sequence
3313//
3314// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3315// and is designed to be a drop-in replacement for C++14's
3316// `std::make_index_sequence`.
3317template <size_t N>
3318using make_index_sequence = make_integer_sequence<size_t, N>;
3319 
3320// index_sequence_for
3321//
3322// Converts a typename pack into an index sequence of the same length, and
3323// is designed to be a drop-in replacement for C++14's
3324// `std::index_sequence_for()`
3325template <typename... Ts>
3326using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3327 
3328//// END OF CODE FROM GOOGLE ABSEIL
3329 
3330#endif
3331 
3332// dispatch utility (taken from ranges-v3)
3333template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3334template<> struct priority_tag<0> {};
3335 
3336// taken from ranges-v3
3337template<typename T>
3338struct static_const
3339{
3340 static JSON_INLINE_VARIABLE constexpr T value{};
3341};
3342 
3343#ifndef JSON_HAS_CPP_17
3344 template<typename T>
3345 constexpr T static_const<T>::value;
3346#endif
3347 
3348template<typename T, typename... Args>
3349constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3350{
3351 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3352}
3353 
3354} // namespace detail
3355NLOHMANN_JSON_NAMESPACE_END
3356 
3357// #include <nlohmann/detail/meta/type_traits.hpp>
3358// __ _____ _____ _____
3359// __| | __| | | | JSON for Modern C++
3360// | | |__ | | | | | | version 3.12.0
3361// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3362//
3363// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3364// SPDX-License-Identifier: MIT
3365 
3366 
3367 
3368#include <limits> // numeric_limits
3369#include <string> // char_traits
3370#include <tuple> // tuple
3371#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3372#include <utility> // declval
3373 
3374// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3375// __ _____ _____ _____
3376// __| | __| | | | JSON for Modern C++
3377// | | |__ | | | | | | version 3.12.0
3378// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3379//
3380// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3381// SPDX-License-Identifier: MIT
3382 
3383 
3384 
3385#include <iterator> // random_access_iterator_tag
3386 
3387// #include <nlohmann/detail/abi_macros.hpp>
3388 
3389// #include <nlohmann/detail/meta/void_t.hpp>
3390 
3391// #include <nlohmann/detail/meta/cpp_future.hpp>
3392 
3393 
3394NLOHMANN_JSON_NAMESPACE_BEGIN
3395namespace detail
3396{
3397 
3398template<typename It, typename = void>
3399struct iterator_types {};
3400 
3401template<typename It>
3402struct iterator_types <
3403 It,
3404 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3405 typename It::reference, typename It::iterator_category >>
3406{
3407 using difference_type = typename It::difference_type;
3408 using value_type = typename It::value_type;
3409 using pointer = typename It::pointer;
3410 using reference = typename It::reference;
3411 using iterator_category = typename It::iterator_category;
3412};
3413 
3414// This is required as some compilers implement std::iterator_traits in a way that
3415// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3416template<typename T, typename = void>
3417struct iterator_traits
3418{
3419};
3420 
3421template<typename T>
3422struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3423 : iterator_types<T>
3424{
3425};
3426 
3427template<typename T>
3428struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3429{
3430 using iterator_category = std::random_access_iterator_tag;
3431 using value_type = T;
3432 using difference_type = ptrdiff_t;
3433 using pointer = T*;
3434 using reference = T&;
3435};
3436 
3437} // namespace detail
3438NLOHMANN_JSON_NAMESPACE_END
3439 
3440// #include <nlohmann/detail/macro_scope.hpp>
3441 
3442// #include <nlohmann/detail/meta/call_std/begin.hpp>
3443// __ _____ _____ _____
3444// __| | __| | | | JSON for Modern C++
3445// | | |__ | | | | | | version 3.12.0
3446// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3447//
3448// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3449// SPDX-License-Identifier: MIT
3450 
3451 
3452 
3453// #include <nlohmann/detail/macro_scope.hpp>
3454 
3455 
3456NLOHMANN_JSON_NAMESPACE_BEGIN
3457 
3458NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3459 
3460NLOHMANN_JSON_NAMESPACE_END
3461 
3462// #include <nlohmann/detail/meta/call_std/end.hpp>
3463// __ _____ _____ _____
3464// __| | __| | | | JSON for Modern C++
3465// | | |__ | | | | | | version 3.12.0
3466// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3467//
3468// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3469// SPDX-License-Identifier: MIT
3470 
3471 
3472 
3473// #include <nlohmann/detail/macro_scope.hpp>
3474 
3475 
3476NLOHMANN_JSON_NAMESPACE_BEGIN
3477 
3478NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3479 
3480NLOHMANN_JSON_NAMESPACE_END
3481 
3482// #include <nlohmann/detail/meta/cpp_future.hpp>
3483 
3484// #include <nlohmann/detail/meta/detected.hpp>
3485 
3486// #include <nlohmann/json_fwd.hpp>
3487// __ _____ _____ _____
3488// __| | __| | | | JSON for Modern C++
3489// | | |__ | | | | | | version 3.12.0
3490// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3491//
3492// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3493// SPDX-License-Identifier: MIT
3494 
3495#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3496 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3497 
3498 #include <cstdint> // int64_t, uint64_t
3499 #include <map> // map
3500 #include <memory> // allocator
3501 #include <string> // string
3502 #include <vector> // vector
3503 
3504 // #include <nlohmann/detail/abi_macros.hpp>
3505 
3506 
3507 /*!
3508 @brief namespace for Niels Lohmann
3509 @see https://github.com/nlohmann
3510 @since version 1.0.0
3511 */
3512 NLOHMANN_JSON_NAMESPACE_BEGIN
3513 
3514 /*!
3515 @brief default JSONSerializer template argument
3516 
3517 This serializer ignores the template arguments and uses ADL
3518 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
3519 for serialization.
3520 */
3521 template<typename T = void, typename SFINAE = void>
3522 struct adl_serializer;
3523 
3524 /// a class to store JSON values
3525 /// @sa https://json.nlohmann.me/api/basic_json/
3526 template<template<typename U, typename V, typename... Args> class ObjectType =
3527 std::map,
3528 template<typename U, typename... Args> class ArrayType = std::vector,
3529 class StringType = std::string, class BooleanType = bool,
3530 class NumberIntegerType = std::int64_t,
3531 class NumberUnsignedType = std::uint64_t,
3532 class NumberFloatType = double,
3533 template<typename U> class AllocatorType = std::allocator,
3534 template<typename T, typename SFINAE = void> class JSONSerializer =
3535 adl_serializer,
3536 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3537 class CustomBaseClass = void>
3538 class basic_json;
3539 
3540 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3541 /// @sa https://json.nlohmann.me/api/json_pointer/
3542 template<typename RefStringType>
3543 class json_pointer;
3544 
3545 /*!
3546 @brief default specialization
3547 @sa https://json.nlohmann.me/api/json/
3548 */
3549 using json = basic_json<>;
3550 
3551 /// @brief a minimal map-like container that preserves insertion order
3552 /// @sa https://json.nlohmann.me/api/ordered_map/
3553 template<class Key, class T, class IgnoredLess, class Allocator>
3554 struct ordered_map;
3555 
3556 /// @brief specialization that maintains the insertion order of object keys
3557 /// @sa https://json.nlohmann.me/api/ordered_json/
3558 using ordered_json = basic_json<nlohmann::ordered_map>;
3559 
3560 NLOHMANN_JSON_NAMESPACE_END
3561 
3562#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3563 
3564 
3565NLOHMANN_JSON_NAMESPACE_BEGIN
3566/*!
3567@brief detail namespace with internal helper functions
3568 
3569This namespace collects functions that should not be exposed,
3570implementations of some @ref basic_json methods, and meta-programming helpers.
3571 
3572@since version 2.1.0
3573*/
3574namespace detail
3575{
3576 
3577/////////////
3578// helpers //
3579/////////////
3580 
3581// Note to maintainers:
3582//
3583// Every trait in this file expects a non CV-qualified type.
3584// The only exceptions are in the 'aliases for detected' section
3585// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3586//
3587// In this case, T has to be properly CV-qualified to constraint the function arguments
3588// (e.g. to_json(BasicJsonType&, const T&))
3589 
3590template<typename> struct is_basic_json : std::false_type {};
3591 
3592NLOHMANN_BASIC_JSON_TPL_DECLARATION
3593struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3594 
3595// used by exceptions create() member functions
3596// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3597// false_type otherwise
3598template<typename BasicJsonContext>
3599struct is_basic_json_context :
3600 std::integral_constant < bool,
3601 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3602 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3603{};
3604 
3605//////////////////////
3606// json_ref helpers //
3607//////////////////////
3608 
3609template<typename>
3610class json_ref;
3611 
3612template<typename>
3613struct is_json_ref : std::false_type {};
3614 
3615template<typename T>
3616struct is_json_ref<json_ref<T>> : std::true_type {};
3617 
3618//////////////////////////
3619// aliases for detected //
3620//////////////////////////
3621 
3622template<typename T>
3623using mapped_type_t = typename T::mapped_type;
3624 
3625template<typename T>
3626using key_type_t = typename T::key_type;
3627 
3628template<typename T>
3629using value_type_t = typename T::value_type;
3630 
3631template<typename T>
3632using difference_type_t = typename T::difference_type;
3633 
3634template<typename T>
3635using pointer_t = typename T::pointer;
3636 
3637template<typename T>
3638using reference_t = typename T::reference;
3639 
3640template<typename T>
3641using iterator_category_t = typename T::iterator_category;
3642 
3643template<typename T, typename... Args>
3644using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3645 
3646template<typename T, typename... Args>
3647using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3648 
3649template<typename T, typename U>
3650using get_template_function = decltype(std::declval<T>().template get<U>());
3651 
3652// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3653template<typename BasicJsonType, typename T, typename = void>
3654struct has_from_json : std::false_type {};
3655 
3656// trait checking if j.get<T> is valid
3657// use this trait instead of std::is_constructible or std::is_convertible,
3658// both rely on, or make use of implicit conversions, and thus fail when T
3659// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3660template <typename BasicJsonType, typename T>
3661struct is_getable
3662{
3663 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3664};
3665 
3666template<typename BasicJsonType, typename T>
3667struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3668{
3669 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3670 
3671 static constexpr bool value =
3672 is_detected_exact<void, from_json_function, serializer,
3673 const BasicJsonType&, T&>::value;
3674};
3675 
3676// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3677// this overload is used for non-default-constructible user-defined-types
3678template<typename BasicJsonType, typename T, typename = void>
3679struct has_non_default_from_json : std::false_type {};
3680 
3681template<typename BasicJsonType, typename T>
3682struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3683{
3684 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3685 
3686 static constexpr bool value =
3687 is_detected_exact<T, from_json_function, serializer,
3688 const BasicJsonType&>::value;
3689};
3690 
3691// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3692// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3693template<typename BasicJsonType, typename T, typename = void>
3694struct has_to_json : std::false_type {};
3695 
3696template<typename BasicJsonType, typename T>
3697struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3698{
3699 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3700 
3701 static constexpr bool value =
3702 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3703 T>::value;
3704};
3705 
3706template<typename T>
3707using detect_key_compare = typename T::key_compare;
3708 
3709template<typename T>
3710struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3711 
3712// obtains the actual object key comparator
3713template<typename BasicJsonType>
3714struct actual_object_comparator
3715{
3716 using object_t = typename BasicJsonType::object_t;
3717 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3718 using type = typename std::conditional < has_key_compare<object_t>::value,
3719 typename object_t::key_compare, object_comparator_t>::type;
3720};
3721 
3722template<typename BasicJsonType>
3723using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3724 
3725/////////////////
3726// char_traits //
3727/////////////////
3728 
3729// Primary template of char_traits calls std char_traits
3730template<typename T>
3731struct char_traits : std::char_traits<T>
3732{};
3733 
3734// Explicitly define char traits for unsigned char since it is not standard
3735template<>
3736struct char_traits<unsigned char> : std::char_traits<char>
3737{
3738 using char_type = unsigned char;
3739 using int_type = uint64_t;
3740 
3741 // Redefine to_int_type function
3742 static int_type to_int_type(char_type c) noexcept
3743 {
3744 return static_cast<int_type>(c);
3745 }
3746 
3747 static char_type to_char_type(int_type i) noexcept
3748 {
3749 return static_cast<char_type>(i);
3750 }
3751 
3752 static constexpr int_type eof() noexcept
3753 {
3754 return static_cast<int_type>(std::char_traits<char>::eof());
3755 }
3756};
3757 
3758// Explicitly define char traits for signed char since it is not standard
3759template<>
3760struct char_traits<signed char> : std::char_traits<char>
3761{
3762 using char_type = signed char;
3763 using int_type = uint64_t;
3764 
3765 // Redefine to_int_type function
3766 static int_type to_int_type(char_type c) noexcept
3767 {
3768 return static_cast<int_type>(c);
3769 }
3770 
3771 static char_type to_char_type(int_type i) noexcept
3772 {
3773 return static_cast<char_type>(i);
3774 }
3775 
3776 static constexpr int_type eof() noexcept
3777 {
3778 return static_cast<int_type>(std::char_traits<char>::eof());
3779 }
3780};
3781 
3782///////////////////
3783// is_ functions //
3784///////////////////
3785 
3786// https://en.cppreference.com/w/cpp/types/conjunction
3787template<class...> struct conjunction : std::true_type { };
3788template<class B> struct conjunction<B> : B { };
3789template<class B, class... Bn>
3790struct conjunction<B, Bn...>
3791: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3792 
3793// https://en.cppreference.com/w/cpp/types/negation
3794template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3795 
3796// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3797// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3798// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3799template <typename T>
3800struct is_default_constructible : std::is_default_constructible<T> {};
3801 
3802template <typename T1, typename T2>
3803struct is_default_constructible<std::pair<T1, T2>>
3804 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3805 
3806template <typename T1, typename T2>
3807struct is_default_constructible<const std::pair<T1, T2>>
3808 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3809 
3810template <typename... Ts>
3811struct is_default_constructible<std::tuple<Ts...>>
3812 : conjunction<is_default_constructible<Ts>...> {};
3813 
3814template <typename... Ts>
3815struct is_default_constructible<const std::tuple<Ts...>>
3816 : conjunction<is_default_constructible<Ts>...> {};
3817 
3818template <typename T, typename... Args>
3819struct is_constructible : std::is_constructible<T, Args...> {};
3820 
3821template <typename T1, typename T2>
3822struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3823 
3824template <typename T1, typename T2>
3825struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3826 
3827template <typename... Ts>
3828struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3829 
3830template <typename... Ts>
3831struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3832 
3833template<typename T, typename = void>
3834struct is_iterator_traits : std::false_type {};
3835 
3836template<typename T>
3837struct is_iterator_traits<iterator_traits<T>>
3838{
3839 private:
3840 using traits = iterator_traits<T>;
3841 
3842 public:
3843 static constexpr auto value =
3844 is_detected<value_type_t, traits>::value &&
3845 is_detected<difference_type_t, traits>::value &&
3846 is_detected<pointer_t, traits>::value &&
3847 is_detected<iterator_category_t, traits>::value &&
3848 is_detected<reference_t, traits>::value;
3849};
3850 
3851template<typename T>
3852struct is_range
3853{
3854 private:
3855 using t_ref = typename std::add_lvalue_reference<T>::type;
3856 
3857 using iterator = detected_t<result_of_begin, t_ref>;
3858 using sentinel = detected_t<result_of_end, t_ref>;
3859 
3860 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3861 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3862 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3863 static constexpr auto is_iterator_begin =
3864 is_iterator_traits<iterator_traits<iterator>>::value;
3865 
3866 public:
3867 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3868};
3869 
3870template<typename R>
3871using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3872 
3873template<typename T>
3874using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3875 
3876// The following implementation of is_complete_type is taken from
3877// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3878// and is written by Xiang Fan who agreed to using it in this library.
3879 
3880template<typename T, typename = void>
3881struct is_complete_type : std::false_type {};
3882 
3883template<typename T>
3884struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3885 
3886template<typename BasicJsonType, typename CompatibleObjectType,
3887 typename = void>
3888struct is_compatible_object_type_impl : std::false_type {};
3889 
3890template<typename BasicJsonType, typename CompatibleObjectType>
3891struct is_compatible_object_type_impl <
3892 BasicJsonType, CompatibleObjectType,
3893 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3894 is_detected<key_type_t, CompatibleObjectType>::value >>
3895{
3896 using object_t = typename BasicJsonType::object_t;
3897 
3898 // macOS's is_constructible does not play well with nonesuch...
3899 static constexpr bool value =
3900 is_constructible<typename object_t::key_type,
3901 typename CompatibleObjectType::key_type>::value &&
3902 is_constructible<typename object_t::mapped_type,
3903 typename CompatibleObjectType::mapped_type>::value;
3904};
3905 
3906template<typename BasicJsonType, typename CompatibleObjectType>
3907struct is_compatible_object_type
3908 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3909 
3910template<typename BasicJsonType, typename ConstructibleObjectType,
3911 typename = void>
3912struct is_constructible_object_type_impl : std::false_type {};
3913 
3914template<typename BasicJsonType, typename ConstructibleObjectType>
3915struct is_constructible_object_type_impl <
3916 BasicJsonType, ConstructibleObjectType,
3917 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3918 is_detected<key_type_t, ConstructibleObjectType>::value >>
3919{
3920 using object_t = typename BasicJsonType::object_t;
3921 
3922 static constexpr bool value =
3923 (is_default_constructible<ConstructibleObjectType>::value &&
3924 (std::is_move_assignable<ConstructibleObjectType>::value ||
3925 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3926 (is_constructible<typename ConstructibleObjectType::key_type,
3927 typename object_t::key_type>::value &&
3928 std::is_same <
3929 typename object_t::mapped_type,
3930 typename ConstructibleObjectType::mapped_type >::value)) ||
3931 (has_from_json<BasicJsonType,
3932 typename ConstructibleObjectType::mapped_type>::value ||
3933 has_non_default_from_json <
3934 BasicJsonType,
3935 typename ConstructibleObjectType::mapped_type >::value);
3936};
3937 
3938template<typename BasicJsonType, typename ConstructibleObjectType>
3939struct is_constructible_object_type
3940 : is_constructible_object_type_impl<BasicJsonType,
3941 ConstructibleObjectType> {};
3942 
3943template<typename BasicJsonType, typename CompatibleStringType>
3944struct is_compatible_string_type
3945{
3946 static constexpr auto value =
3947 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3948};
3949 
3950template<typename BasicJsonType, typename ConstructibleStringType>
3951struct is_constructible_string_type
3952{
3953 // launder type through decltype() to fix compilation failure on ICPC
3954#ifdef __INTEL_COMPILER
3955 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3956#else
3957 using laundered_type = ConstructibleStringType;
3958#endif
3959 
3960 static constexpr auto value =
3961 conjunction <
3962 is_constructible<laundered_type, typename BasicJsonType::string_t>,
3963 is_detected_exact<typename BasicJsonType::string_t::value_type,
3964 value_type_t, laundered_type >>::value;
3965};
3966 
3967template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3968struct is_compatible_array_type_impl : std::false_type {};
3969 
3970template<typename BasicJsonType, typename CompatibleArrayType>
3971struct is_compatible_array_type_impl <
3972 BasicJsonType, CompatibleArrayType,
3973 enable_if_t <
3974 is_detected<iterator_t, CompatibleArrayType>::value&&
3975 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3976// special case for types like std::filesystem::path whose iterator's value_type are themselves
3977// c.f. https://github.com/nlohmann/json/pull/3073
3978 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3979{
3980 static constexpr bool value =
3981 is_constructible<BasicJsonType,
3982 range_value_t<CompatibleArrayType>>::value;
3983};
3984 
3985template<typename BasicJsonType, typename CompatibleArrayType>
3986struct is_compatible_array_type
3987 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3988 
3989template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3990struct is_constructible_array_type_impl : std::false_type {};
3991 
3992template<typename BasicJsonType, typename ConstructibleArrayType>
3993struct is_constructible_array_type_impl <
3994 BasicJsonType, ConstructibleArrayType,
3995 enable_if_t<std::is_same<ConstructibleArrayType,
3996 typename BasicJsonType::value_type>::value >>
3997 : std::true_type {};
3998 
3999template<typename BasicJsonType, typename ConstructibleArrayType>
4000struct is_constructible_array_type_impl <
4001 BasicJsonType, ConstructibleArrayType,
4002 enable_if_t < !std::is_same<ConstructibleArrayType,
4003 typename BasicJsonType::value_type>::value&&
4004 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4005 is_default_constructible<ConstructibleArrayType>::value&&
4006(std::is_move_assignable<ConstructibleArrayType>::value ||
4007 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4008is_detected<iterator_t, ConstructibleArrayType>::value&&
4009is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4010is_detected<range_value_t, ConstructibleArrayType>::value&&
4011// special case for types like std::filesystem::path whose iterator's value_type are themselves
4012// c.f. https://github.com/nlohmann/json/pull/3073
4013!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4014is_complete_type <
4015detected_t<range_value_t, ConstructibleArrayType >>::value >>
4016{
4017 using value_type = range_value_t<ConstructibleArrayType>;
4018 
4019 static constexpr bool value =
4020 std::is_same<value_type,
4021 typename BasicJsonType::array_t::value_type>::value ||
4022 has_from_json<BasicJsonType,
4023 value_type>::value ||
4024 has_non_default_from_json <
4025 BasicJsonType,
4026 value_type >::value;
4027};
4028 
4029template<typename BasicJsonType, typename ConstructibleArrayType>
4030struct is_constructible_array_type
4031 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4032 
4033template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4034 typename = void>
4035struct is_compatible_integer_type_impl : std::false_type {};
4036 
4037template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4038struct is_compatible_integer_type_impl <
4039 RealIntegerType, CompatibleNumberIntegerType,
4040 enable_if_t < std::is_integral<RealIntegerType>::value&&
4041 std::is_integral<CompatibleNumberIntegerType>::value&&
4042 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4043{
4044 // is there an assert somewhere on overflows?
4045 using RealLimits = std::numeric_limits<RealIntegerType>;
4046 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4047 
4048 static constexpr auto value =
4049 is_constructible<RealIntegerType,
4050 CompatibleNumberIntegerType>::value &&
4051 CompatibleLimits::is_integer &&
4052 RealLimits::is_signed == CompatibleLimits::is_signed;
4053};
4054 
4055template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4056struct is_compatible_integer_type
4057 : is_compatible_integer_type_impl<RealIntegerType,
4058 CompatibleNumberIntegerType> {};
4059 
4060template<typename BasicJsonType, typename CompatibleType, typename = void>
4061struct is_compatible_type_impl: std::false_type {};
4062 
4063template<typename BasicJsonType, typename CompatibleType>
4064struct is_compatible_type_impl <
4065 BasicJsonType, CompatibleType,
4066 enable_if_t<is_complete_type<CompatibleType>::value >>
4067{
4068 static constexpr bool value =
4069 has_to_json<BasicJsonType, CompatibleType>::value;
4070};
4071 
4072template<typename BasicJsonType, typename CompatibleType>
4073struct is_compatible_type
4074 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4075 
4076template<typename T1, typename T2>
4077struct is_constructible_tuple : std::false_type {};
4078 
4079template<typename T1, typename... Args>
4080struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4081 
4082template<typename BasicJsonType, typename T>
4083struct is_json_iterator_of : std::false_type {};
4084 
4085template<typename BasicJsonType>
4086struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4087 
4088template<typename BasicJsonType>
4089struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4090{};
4091 
4092// checks if a given type T is a template specialization of Primary
4093template<template <typename...> class Primary, typename T>
4094struct is_specialization_of : std::false_type {};
4095 
4096template<template <typename...> class Primary, typename... Args>
4097struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4098 
4099template<typename T>
4100using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
4101 
4102// checks if A and B are comparable using Compare functor
4103template<typename Compare, typename A, typename B, typename = void>
4104struct is_comparable : std::false_type {};
4105 
4106template<typename Compare, typename A, typename B>
4107struct is_comparable<Compare, A, B, void_t<
4108decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4109decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4110>> : std::true_type {};
4111 
4112template<typename T>
4113using detect_is_transparent = typename T::is_transparent;
4114 
4115// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4116// see is_usable_as_basic_json_key_type below
4117template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4118 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4119using is_usable_as_key_type = typename std::conditional <
4120 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
4121 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4122 ObjectKeyType>::value)
4123 && (!RequireTransparentComparator
4124 || is_detected <detect_is_transparent, Comparator>::value)
4125 && !is_json_pointer<KeyType>::value,
4126 std::true_type,
4127 std::false_type >::type;
4128 
4129// type trait to check if KeyType can be used as object key
4130// true if:
4131// - KeyType is comparable with BasicJsonType::object_t::key_type
4132// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4133// - the comparator is transparent or RequireTransparentComparator is false
4134// - KeyType is not a JSON iterator or json_pointer
4135template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4136 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4137using is_usable_as_basic_json_key_type = typename std::conditional <
4138 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4139 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4140 RequireTransparentComparator, ExcludeObjectKeyType>::value
4141 && !is_json_iterator_of<BasicJsonType, KeyType>::value,
4142 std::true_type,
4143 std::false_type >::type;
4144 
4145template<typename ObjectType, typename KeyType>
4146using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4147 
4148// type trait to check if object_t has an erase() member functions accepting KeyType
4149template<typename BasicJsonType, typename KeyType>
4150using has_erase_with_key_type = typename std::conditional <
4151 is_detected <
4152 detect_erase_with_key_type,
4153 typename BasicJsonType::object_t, KeyType >::value,
4154 std::true_type,
4155 std::false_type >::type;
4156 
4157// a naive helper to check if a type is an ordered_map (exploits the fact that
4158// ordered_map inherits capacity() from std::vector)
4159template <typename T>
4160struct is_ordered_map
4161{
4162 using one = char;
4163 
4164 struct two
4165 {
4166 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4167 };
4168 
4169 template <typename C> static one test( decltype(&C::capacity) ) ;
4170 template <typename C> static two test(...);
4171 
4172 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4173};
4174 
4175// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4176template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4177T conditional_static_cast(U value)
4178{
4179 return static_cast<T>(value);
4180}
4181 
4182template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4183T conditional_static_cast(U value)
4184{
4185 return value;
4186}
4187 
4188template<typename... Types>
4189using all_integral = conjunction<std::is_integral<Types>...>;
4190 
4191template<typename... Types>
4192using all_signed = conjunction<std::is_signed<Types>...>;
4193 
4194template<typename... Types>
4195using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4196 
4197// there's a disjunction trait in another PR; replace when merged
4198template<typename... Types>
4199using same_sign = std::integral_constant < bool,
4200 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4201 
4202template<typename OfType, typename T>
4203using never_out_of_range = std::integral_constant < bool,
4204 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4205 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4206 
4207template<typename OfType, typename T,
4208 bool OfTypeSigned = std::is_signed<OfType>::value,
4209 bool TSigned = std::is_signed<T>::value>
4210struct value_in_range_of_impl2;
4211 
4212template<typename OfType, typename T>
4213struct value_in_range_of_impl2<OfType, T, false, false>
4214{
4215 static constexpr bool test(T val)
4216 {
4217 using CommonType = typename std::common_type<OfType, T>::type;
4218 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4219 }
4220};
4221 
4222template<typename OfType, typename T>
4223struct value_in_range_of_impl2<OfType, T, true, false>
4224{
4225 static constexpr bool test(T val)
4226 {
4227 using CommonType = typename std::common_type<OfType, T>::type;
4228 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4229 }
4230};
4231 
4232template<typename OfType, typename T>
4233struct value_in_range_of_impl2<OfType, T, false, true>
4234{
4235 static constexpr bool test(T val)
4236 {
4237 using CommonType = typename std::common_type<OfType, T>::type;
4238 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4239 }
4240};
4241 
4242template<typename OfType, typename T>
4243struct value_in_range_of_impl2<OfType, T, true, true>
4244{
4245 static constexpr bool test(T val)
4246 {
4247 using CommonType = typename std::common_type<OfType, T>::type;
4248 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4249 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4250 }
4251};
4252 
4253template<typename OfType, typename T,
4254 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4255 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4256struct value_in_range_of_impl1;
4257 
4258template<typename OfType, typename T>
4259struct value_in_range_of_impl1<OfType, T, false>
4260{
4261 static constexpr bool test(T val)
4262 {
4263 return value_in_range_of_impl2<OfType, T>::test(val);
4264 }
4265};
4266 
4267template<typename OfType, typename T>
4268struct value_in_range_of_impl1<OfType, T, true>
4269{
4270 static constexpr bool test(T /*val*/)
4271 {
4272 return true;
4273 }
4274};
4275 
4276template<typename OfType, typename T>
4277constexpr bool value_in_range_of(T val)
4278{
4279 return value_in_range_of_impl1<OfType, T>::test(val);
4280}
4281 
4282template<bool Value>
4283using bool_constant = std::integral_constant<bool, Value>;
4284 
4285///////////////////////////////////////////////////////////////////////////////
4286// is_c_string
4287///////////////////////////////////////////////////////////////////////////////
4288 
4289namespace impl
4290{
4291 
4292template<typename T>
4293constexpr bool is_c_string()
4294{
4295 using TUnExt = typename std::remove_extent<T>::type;
4296 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4297 using TUnPtr = typename std::remove_pointer<T>::type;
4298 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4299 return
4300 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4301 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4302}
4303 
4304} // namespace impl
4305 
4306// checks whether T is a [cv] char */[cv] char[] C string
4307template<typename T>
4308struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4309 
4310template<typename T>
4311using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4312 
4313///////////////////////////////////////////////////////////////////////////////
4314// is_transparent
4315///////////////////////////////////////////////////////////////////////////////
4316 
4317namespace impl
4318{
4319 
4320template<typename T>
4321constexpr bool is_transparent()
4322{
4323 return is_detected<detect_is_transparent, T>::value;
4324}
4325 
4326} // namespace impl
4327 
4328// checks whether T has a member named is_transparent
4329template<typename T>
4330struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4331 
4332///////////////////////////////////////////////////////////////////////////////
4333 
4334} // namespace detail
4335NLOHMANN_JSON_NAMESPACE_END
4336 
4337// #include <nlohmann/detail/string_concat.hpp>
4338// __ _____ _____ _____
4339// __| | __| | | | JSON for Modern C++
4340// | | |__ | | | | | | version 3.12.0
4341// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4342//
4343// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4344// SPDX-License-Identifier: MIT
4345 
4346 
4347 
4348#include <cstring> // strlen
4349#include <string> // string
4350#include <utility> // forward
4351 
4352// #include <nlohmann/detail/meta/cpp_future.hpp>
4353 
4354// #include <nlohmann/detail/meta/detected.hpp>
4355 
4356 
4357NLOHMANN_JSON_NAMESPACE_BEGIN
4358namespace detail
4359{
4360 
4361inline std::size_t concat_length()
4362{
4363 return 0;
4364}
4365 
4366template<typename... Args>
4367inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4368 
4369template<typename StringType, typename... Args>
4370inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4371 
4372template<typename... Args>
4373inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4374{
4375 return 1 + concat_length(rest...);
4376}
4377 
4378template<typename... Args>
4379inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4380{
4381 // cppcheck-suppress ignoredReturnValue
4382 return ::strlen(cstr) + concat_length(rest...);
4383}
4384 
4385template<typename StringType, typename... Args>
4386inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4387{
4388 return str.size() + concat_length(rest...);
4389}
4390 
4391template<typename OutStringType>
4392inline void concat_into(OutStringType& /*out*/)
4393{}
4394 
4395template<typename StringType, typename Arg>
4396using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4397 
4398template<typename StringType, typename Arg>
4399using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4400 
4401template<typename StringType, typename Arg>
4402using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4403 
4404template<typename StringType, typename Arg>
4405using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4406 
4407template<typename StringType, typename Arg>
4408using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4409 
4410template<typename StringType, typename Arg>
4411using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4412 
4413template<typename StringType, typename Arg>
4414using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4415 
4416template<typename StringType, typename Arg>
4417using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4418 
4419template < typename OutStringType, typename Arg, typename... Args,
4420 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4421 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4422inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4423 
4424template < typename OutStringType, typename Arg, typename... Args,
4425 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4426 && !detect_string_can_append_op<OutStringType, Arg>::value
4427 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4428inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4429 
4430template < typename OutStringType, typename Arg, typename... Args,
4431 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4432 && !detect_string_can_append_op<OutStringType, Arg>::value
4433 && !detect_string_can_append_iter<OutStringType, Arg>::value
4434 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4435inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4436 
4437template<typename OutStringType, typename Arg, typename... Args,
4438 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4439inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4440{
4441 out.append(std::forward<Arg>(arg));
4442 concat_into(out, std::forward<Args>(rest)...);
4443}
4444 
4445template < typename OutStringType, typename Arg, typename... Args,
4446 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4447 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4448inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4449{
4450 out += std::forward<Arg>(arg);
4451 concat_into(out, std::forward<Args>(rest)...);
4452}
4453 
4454template < typename OutStringType, typename Arg, typename... Args,
4455 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4456 && !detect_string_can_append_op<OutStringType, Arg>::value
4457 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4458inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4459{
4460 out.append(arg.begin(), arg.end());
4461 concat_into(out, std::forward<Args>(rest)...);
4462}
4463 
4464template < typename OutStringType, typename Arg, typename... Args,
4465 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4466 && !detect_string_can_append_op<OutStringType, Arg>::value
4467 && !detect_string_can_append_iter<OutStringType, Arg>::value
4468 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4469inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4470{
4471 out.append(arg.data(), arg.size());
4472 concat_into(out, std::forward<Args>(rest)...);
4473}
4474 
4475template<typename OutStringType = std::string, typename... Args>
4476inline OutStringType concat(Args && ... args)
4477{
4478 OutStringType str;
4479 str.reserve(concat_length(args...));
4480 concat_into(str, std::forward<Args>(args)...);
4481 return str;
4482}
4483 
4484} // namespace detail
4485NLOHMANN_JSON_NAMESPACE_END
4486 
4487 
4488// With -Wweak-vtables, Clang will complain about the exception classes as they
4489// have no out-of-line virtual method definitions and their vtable will be
4490// emitted in every translation unit. This issue cannot be fixed with a
4491// header-only library as there is no implementation file to move these
4492// functions to. As a result, we suppress this warning here to avoid client
4493// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
4494// for a discussion.
4495#if defined(__clang__)
4496 #pragma clang diagnostic push
4497 #pragma clang diagnostic ignored "-Wweak-vtables"
4498#endif
4499 
4500NLOHMANN_JSON_NAMESPACE_BEGIN
4501namespace detail
4502{
4503 
4504////////////////
4505// exceptions //
4506////////////////
4507 
4508/// @brief general exception of the @ref basic_json class
4509/// @sa https://json.nlohmann.me/api/basic_json/exception/
4510class exception : public std::exception
4511{
4512 public:
4513 /// returns the explanatory string
4514 const char* what() const noexcept override
4515 {
4516 return m.what();
4517 }
4518 
4519 /// the id of the exception
4520 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4521 
4522 protected:
4523 JSON_HEDLEY_NON_NULL(3)
4524 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4525 
4526 static std::string name(const std::string& ename, int id_)
4527 {
4528 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4529 }
4530 
4531 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4532 {
4533 return "";
4534 }
4535 
4536 template<typename BasicJsonType>
4537 static std::string diagnostics(const BasicJsonType* leaf_element)
4538 {
4539#if JSON_DIAGNOSTICS
4540 std::vector<std::string> tokens;
4541 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4542 {
4543 switch (current->m_parent->type())
4544 {
4545 case value_t::array:
4546 {
4547 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4548 {
4549 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4550 {
4551 tokens.emplace_back(std::to_string(i));
4552 break;
4553 }
4554 }
4555 break;
4556 }
4557 
4558 case value_t::object:
4559 {
4560 for (const auto& element : *current->m_parent->m_data.m_value.object)
4561 {
4562 if (&element.second == current)
4563 {
4564 tokens.emplace_back(element.first.c_str());
4565 break;
4566 }
4567 }
4568 break;
4569 }
4570 
4571 case value_t::null: // LCOV_EXCL_LINE
4572 case value_t::string: // LCOV_EXCL_LINE
4573 case value_t::boolean: // LCOV_EXCL_LINE
4574 case value_t::number_integer: // LCOV_EXCL_LINE
4575 case value_t::number_unsigned: // LCOV_EXCL_LINE
4576 case value_t::number_float: // LCOV_EXCL_LINE
4577 case value_t::binary: // LCOV_EXCL_LINE
4578 case value_t::discarded: // LCOV_EXCL_LINE
4579 default: // LCOV_EXCL_LINE
4580 break; // LCOV_EXCL_LINE
4581 }
4582 }
4583 
4584 if (tokens.empty())
4585 {
4586 return "";
4587 }
4588 
4589 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4590 [](const std::string & a, const std::string & b)
4591 {
4592 return concat(a, '/', detail::escape(b));
4593 });
4594 
4595 return concat('(', str, ") ", get_byte_positions(leaf_element));
4596#else
4597 return get_byte_positions(leaf_element);
4598#endif
4599 }
4600 
4601 private:
4602 /// an exception object as storage for error messages
4603 std::runtime_error m;
4604#if JSON_DIAGNOSTIC_POSITIONS
4605 template<typename BasicJsonType>
4606 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4607 {
4608 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4609 {
4610 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4611 }
4612 return "";
4613 }
4614#else
4615 template<typename BasicJsonType>
4616 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4617 {
4618 static_cast<void>(leaf_element);
4619 return "";
4620 }
4621#endif
4622};
4623 
4624/// @brief exception indicating a parse error
4625/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4626class parse_error : public exception
4627{
4628 public:
4629 /*!
4630 @brief create a parse error exception
4631 @param[in] id_ the id of the exception
4632 @param[in] pos the position where the error occurred (or with
4633 chars_read_total=0 if the position cannot be
4634 determined)
4635 @param[in] what_arg the explanatory string
4636 @return parse_error object
4637 */
4638 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4639 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4640 {
4641 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4642 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4643 return {id_, pos.chars_read_total, w.c_str()};
4644 }
4645 
4646 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4647 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4648 {
4649 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4650 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4651 ": ", exception::diagnostics(context), what_arg);
4652 return {id_, byte_, w.c_str()};
4653 }
4654 
4655 /*!
4656 @brief byte index of the parse error
4657 
4658 The byte index of the last read character in the input file.
4659 
4660 @note For an input with n bytes, 1 is the index of the first character and
4661 n+1 is the index of the terminating null byte or the end of file.
4662 This also holds true when reading a byte vector (CBOR or MessagePack).
4663 */
4664 const std::size_t byte;
4665 
4666 private:
4667 parse_error(int id_, std::size_t byte_, const char* what_arg)
4668 : exception(id_, what_arg), byte(byte_) {}
4669 
4670 static std::string position_string(const position_t& pos)
4671 {
4672 return concat(" at line ", std::to_string(pos.lines_read + 1),
4673 ", column ", std::to_string(pos.chars_read_current_line));
4674 }
4675};
4676 
4677/// @brief exception indicating errors with iterators
4678/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4679class invalid_iterator : public exception
4680{
4681 public:
4682 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4683 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4684 {
4685 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4686 return {id_, w.c_str()};
4687 }
4688 
4689 private:
4690 JSON_HEDLEY_NON_NULL(3)
4691 invalid_iterator(int id_, const char* what_arg)
4692 : exception(id_, what_arg) {}
4693};
4694 
4695/// @brief exception indicating executing a member function with a wrong type
4696/// @sa https://json.nlohmann.me/api/basic_json/type_error/
4697class type_error : public exception
4698{
4699 public:
4700 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4701 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4702 {
4703 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4704 return {id_, w.c_str()};
4705 }
4706 
4707 private:
4708 JSON_HEDLEY_NON_NULL(3)
4709 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4710};
4711 
4712/// @brief exception indicating access out of the defined range
4713/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4714class out_of_range : public exception
4715{
4716 public:
4717 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4718 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4719 {
4720 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4721 return {id_, w.c_str()};
4722 }
4723 
4724 private:
4725 JSON_HEDLEY_NON_NULL(3)
4726 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4727};
4728 
4729/// @brief exception indicating other library errors
4730/// @sa https://json.nlohmann.me/api/basic_json/other_error/
4731class other_error : public exception
4732{
4733 public:
4734 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4735 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4736 {
4737 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4738 return {id_, w.c_str()};
4739 }
4740 
4741 private:
4742 JSON_HEDLEY_NON_NULL(3)
4743 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4744};
4745 
4746} // namespace detail
4747NLOHMANN_JSON_NAMESPACE_END
4748 
4749#if defined(__clang__)
4750 #pragma clang diagnostic pop
4751#endif
4752 
4753// #include <nlohmann/detail/macro_scope.hpp>
4754 
4755// #include <nlohmann/detail/meta/cpp_future.hpp>
4756 
4757// #include <nlohmann/detail/meta/identity_tag.hpp>
4758// __ _____ _____ _____
4759// __| | __| | | | JSON for Modern C++
4760// | | |__ | | | | | | version 3.12.0
4761// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4762//
4763// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4764// SPDX-License-Identifier: MIT
4765 
4766 
4767 
4768// #include <nlohmann/detail/abi_macros.hpp>
4769 
4770 
4771NLOHMANN_JSON_NAMESPACE_BEGIN
4772namespace detail
4773{
4774 
4775// dispatching helper struct
4776template <class T> struct identity_tag {};
4777 
4778} // namespace detail
4779NLOHMANN_JSON_NAMESPACE_END
4780 
4781// #include <nlohmann/detail/meta/std_fs.hpp>
4782// __ _____ _____ _____
4783// __| | __| | | | JSON for Modern C++
4784// | | |__ | | | | | | version 3.12.0
4785// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4786//
4787// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4788// SPDX-License-Identifier: MIT
4789 
4790 
4791 
4792// #include <nlohmann/detail/macro_scope.hpp>
4793 
4794 
4795#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4796#include <experimental/filesystem>
4797NLOHMANN_JSON_NAMESPACE_BEGIN
4798namespace detail
4799{
4800namespace std_fs = std::experimental::filesystem;
4801} // namespace detail
4802NLOHMANN_JSON_NAMESPACE_END
4803#elif JSON_HAS_FILESYSTEM
4804#include <filesystem> // NOLINT(build/c++17)
4805NLOHMANN_JSON_NAMESPACE_BEGIN
4806namespace detail
4807{
4808namespace std_fs = std::filesystem;
4809} // namespace detail
4810NLOHMANN_JSON_NAMESPACE_END
4811#endif
4812 
4813// #include <nlohmann/detail/meta/type_traits.hpp>
4814 
4815// #include <nlohmann/detail/string_concat.hpp>
4816 
4817// #include <nlohmann/detail/value_t.hpp>
4818 
4819 
4820NLOHMANN_JSON_NAMESPACE_BEGIN
4821namespace detail
4822{
4823 
4824template<typename BasicJsonType>
4825inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4826{
4827 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4828 {
4829 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4830 }
4831 n = nullptr;
4832}
4833 
4834#ifdef JSON_HAS_CPP_17
4835#ifndef JSON_USE_IMPLICIT_CONVERSIONS
4836template<typename BasicJsonType, typename T>
4837void from_json(const BasicJsonType& j, std::optional<T>& opt)
4838{
4839 if (j.is_null())
4840 {
4841 opt = std::nullopt;
4842 }
4843 else
4844 {
4845 opt.emplace(j.template get<T>());
4846 }
4847}
4848 
4849#endif // JSON_USE_IMPLICIT_CONVERSIONS
4850#endif // JSON_HAS_CPP_17
4851 
4852// overloads for basic_json template parameters
4853template < typename BasicJsonType, typename ArithmeticType,
4854 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4855 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4856 int > = 0 >
4857void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4858{
4859 switch (static_cast<value_t>(j))
4860 {
4861 case value_t::number_unsigned:
4862 {
4863 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4864 break;
4865 }
4866 case value_t::number_integer:
4867 {
4868 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4869 break;
4870 }
4871 case value_t::number_float:
4872 {
4873 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4874 break;
4875 }
4876 
4877 case value_t::null:
4878 case value_t::object:
4879 case value_t::array:
4880 case value_t::string:
4881 case value_t::boolean:
4882 case value_t::binary:
4883 case value_t::discarded:
4884 default:
4885 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4886 }
4887}
4888 
4889template<typename BasicJsonType>
4890inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4891{
4892 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4893 {
4894 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4895 }
4896 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4897}
4898 
4899template<typename BasicJsonType>
4900inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4901{
4902 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4903 {
4904 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4905 }
4906 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4907}
4908 
4909template <
4910 typename BasicJsonType, typename StringType,
4911 enable_if_t <
4912 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4913 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4914 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4915 && !is_json_ref<StringType>::value, int > = 0 >
4916inline void from_json(const BasicJsonType& j, StringType& s)
4917{
4918 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4919 {
4920 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4921 }
4922 
4923 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4924}
4925 
4926template<typename BasicJsonType>
4927inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4928{
4929 get_arithmetic_value(j, val);
4930}
4931 
4932template<typename BasicJsonType>
4933inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4934{
4935 get_arithmetic_value(j, val);
4936}
4937 
4938template<typename BasicJsonType>
4939inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4940{
4941 get_arithmetic_value(j, val);
4942}
4943 
4944#if !JSON_DISABLE_ENUM_SERIALIZATION
4945template<typename BasicJsonType, typename EnumType,
4946 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4947inline void from_json(const BasicJsonType& j, EnumType& e)
4948{
4949 typename std::underlying_type<EnumType>::type val;
4950 get_arithmetic_value(j, val);
4951 e = static_cast<EnumType>(val);
4952}
4953#endif // JSON_DISABLE_ENUM_SERIALIZATION
4954 
4955// forward_list doesn't have an insert method
4956template<typename BasicJsonType, typename T, typename Allocator,
4957 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4958inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4959{
4960 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4961 {
4962 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4963 }
4964 l.clear();
4965 std::transform(j.rbegin(), j.rend(),
4966 std::front_inserter(l), [](const BasicJsonType & i)
4967 {
4968 return i.template get<T>();
4969 });
4970}
4971 
4972// valarray doesn't have an insert method
4973template<typename BasicJsonType, typename T,
4974 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4975inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4976{
4977 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4978 {
4979 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4980 }
4981 l.resize(j.size());
4982 std::transform(j.begin(), j.end(), std::begin(l),
4983 [](const BasicJsonType & elem)
4984 {
4985 return elem.template get<T>();
4986 });
4987}
4988 
4989template<typename BasicJsonType, typename T, std::size_t N>
4990auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4991-> decltype(j.template get<T>(), void())
4992{
4993 for (std::size_t i = 0; i < N; ++i)
4994 {
4995 arr[i] = j.at(i).template get<T>();
4996 }
4997}
4998 
4999template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5000auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5001-> decltype(j.template get<T>(), void())
5002{
5003 for (std::size_t i1 = 0; i1 < N1; ++i1)
5004 {
5005 for (std::size_t i2 = 0; i2 < N2; ++i2)
5006 {
5007 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5008 }
5009 }
5010}
5011 
5012template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5013auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5014-> decltype(j.template get<T>(), void())
5015{
5016 for (std::size_t i1 = 0; i1 < N1; ++i1)
5017 {
5018 for (std::size_t i2 = 0; i2 < N2; ++i2)
5019 {
5020 for (std::size_t i3 = 0; i3 < N3; ++i3)
5021 {
5022 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5023 }
5024 }
5025 }
5026}
5027 
5028template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5029auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5030-> decltype(j.template get<T>(), void())
5031{
5032 for (std::size_t i1 = 0; i1 < N1; ++i1)
5033 {
5034 for (std::size_t i2 = 0; i2 < N2; ++i2)
5035 {
5036 for (std::size_t i3 = 0; i3 < N3; ++i3)
5037 {
5038 for (std::size_t i4 = 0; i4 < N4; ++i4)
5039 {
5040 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5041 }
5042 }
5043 }
5044 }
5045}
5046 
5047template<typename BasicJsonType>
5048inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5049{
5050 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5051}
5052 
5053template<typename BasicJsonType, typename T, std::size_t N>
5054auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5055 priority_tag<2> /*unused*/)
5056-> decltype(j.template get<T>(), void())
5057{
5058 for (std::size_t i = 0; i < N; ++i)
5059 {
5060 arr[i] = j.at(i).template get<T>();
5061 }
5062}
5063 
5064template<typename BasicJsonType, typename ConstructibleArrayType,
5065 enable_if_t<
5066 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5067 int> = 0>
5068auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5069-> decltype(
5070 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5071 j.template get<typename ConstructibleArrayType::value_type>(),
5072 void())
5073{
5074 using std::end;
5075 
5076 ConstructibleArrayType ret;
5077 ret.reserve(j.size());
5078 std::transform(j.begin(), j.end(),
5079 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5080 {
5081 // get<BasicJsonType>() returns *this, this won't call a from_json
5082 // method when value_type is BasicJsonType
5083 return i.template get<typename ConstructibleArrayType::value_type>();
5084 });
5085 arr = std::move(ret);
5086}
5087 
5088template<typename BasicJsonType, typename ConstructibleArrayType,
5089 enable_if_t<
5090 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5091 int> = 0>
5092inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5093 priority_tag<0> /*unused*/)
5094{
5095 using std::end;
5096 
5097 ConstructibleArrayType ret;
5098 std::transform(
5099 j.begin(), j.end(), std::inserter(ret, end(ret)),
5100 [](const BasicJsonType & i)
5101 {
5102 // get<BasicJsonType>() returns *this, this won't call a from_json
5103 // method when value_type is BasicJsonType
5104 return i.template get<typename ConstructibleArrayType::value_type>();
5105 });
5106 arr = std::move(ret);
5107}
5108 
5109template < typename BasicJsonType, typename ConstructibleArrayType,
5110 enable_if_t <
5111 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5112 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5113 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
5114 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5115 !is_basic_json<ConstructibleArrayType>::value,
5116 int > = 0 >
5117auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5118-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5119j.template get<typename ConstructibleArrayType::value_type>(),
5120void())
5121{
5122 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5123 {
5124 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5125 }
5126 
5127 from_json_array_impl(j, arr, priority_tag<3> {});
5128}
5129 
5130template < typename BasicJsonType, typename T, std::size_t... Idx >
5131std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5132 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5133{
5134 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5135}
5136 
5137template < typename BasicJsonType, typename T, std::size_t N >
5138auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5139-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5140{
5141 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5142 {
5143 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5144 }
5145 
5146 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5147}
5148 
5149template<typename BasicJsonType>
5150inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5151{
5152 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5153 {
5154 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5155 }
5156 
5157 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5158}
5159 
5160template<typename BasicJsonType, typename ConstructibleObjectType,
5161 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5162inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5163{
5164 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5165 {
5166 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5167 }
5168 
5169 ConstructibleObjectType ret;
5170 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5171 using value_type = typename ConstructibleObjectType::value_type;
5172 std::transform(
5173 inner_object->begin(), inner_object->end(),
5174 std::inserter(ret, ret.begin()),
5175 [](typename BasicJsonType::object_t::value_type const & p)
5176 {
5177 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5178 });
5179 obj = std::move(ret);
5180}
5181 
5182// overload for arithmetic types, not chosen for basic_json template arguments
5183// (BooleanType, etc..); note: Is it really necessary to provide explicit
5184// overloads for boolean_t etc. in case of a custom BooleanType which is not
5185// an arithmetic type?
5186template < typename BasicJsonType, typename ArithmeticType,
5187 enable_if_t <
5188 std::is_arithmetic<ArithmeticType>::value&&
5189 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5190 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5191 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5192 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5193 int > = 0 >
5194inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5195{
5196 switch (static_cast<value_t>(j))
5197 {
5198 case value_t::number_unsigned:
5199 {
5200 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5201 break;
5202 }
5203 case value_t::number_integer:
5204 {
5205 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5206 break;
5207 }
5208 case value_t::number_float:
5209 {
5210 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5211 break;
5212 }
5213 case value_t::boolean:
5214 {
5215 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5216 break;
5217 }
5218 
5219 case value_t::null:
5220 case value_t::object:
5221 case value_t::array:
5222 case value_t::string:
5223 case value_t::binary:
5224 case value_t::discarded:
5225 default:
5226 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5227 }
5228}
5229 
5230template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5231std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5232{
5233 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5234}
5235 
5236template<typename BasicJsonType>
5237std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5238{
5239 return {};
5240}
5241 
5242template < typename BasicJsonType, class A1, class A2 >
5243std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5244{
5245 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5246 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5247}
5248 
5249template<typename BasicJsonType, typename A1, typename A2>
5250inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5251{
5252 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5253}
5254 
5255template<typename BasicJsonType, typename... Args>
5256std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5257{
5258 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5259}
5260 
5261template<typename BasicJsonType, typename... Args>
5262inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5263{
5264 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5265}
5266 
5267template<typename BasicJsonType, typename TupleRelated>
5268auto from_json(BasicJsonType&& j, TupleRelated&& t)
5269-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5270{
5271 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5272 {
5273 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5274 }
5275 
5276 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5277}
5278 
5279template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5280 typename = enable_if_t < !std::is_constructible <
5281 typename BasicJsonType::string_t, Key >::value >>
5282inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5283{
5284 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5285 {
5286 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5287 }
5288 m.clear();
5289 for (const auto& p : j)
5290 {
5291 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5292 {
5293 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5294 }
5295 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5296 }
5297}
5298 
5299template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5300 typename = enable_if_t < !std::is_constructible <
5301 typename BasicJsonType::string_t, Key >::value >>
5302inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5303{
5304 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5305 {
5306 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5307 }
5308 m.clear();
5309 for (const auto& p : j)
5310 {
5311 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5312 {
5313 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5314 }
5315 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5316 }
5317}
5318 
5319#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5320template<typename BasicJsonType>
5321inline void from_json(const BasicJsonType& j, std_fs::path& p)
5322{
5323 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5324 {
5325 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5326 }
5327 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5328#ifdef JSON_HAS_CPP_20
5329 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5330#else
5331 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5332#endif
5333}
5334#endif
5335 
5336struct from_json_fn
5337{
5338 template<typename BasicJsonType, typename T>
5339 auto operator()(const BasicJsonType& j, T&& val) const
5340 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5341 -> decltype(from_json(j, std::forward<T>(val)))
5342 {
5343 return from_json(j, std::forward<T>(val));
5344 }
5345};
5346 
5347} // namespace detail
5348 
5349#ifndef JSON_HAS_CPP_17
5350/// namespace to hold default `from_json` function
5351/// to see why this is required:
5352/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5353namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5354{
5355#endif
5356JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5357 detail::static_const<detail::from_json_fn>::value;
5358#ifndef JSON_HAS_CPP_17
5359} // namespace
5360#endif
5361 
5362NLOHMANN_JSON_NAMESPACE_END
5363 
5364// #include <nlohmann/detail/conversions/to_json.hpp>
5365// __ _____ _____ _____
5366// __| | __| | | | JSON for Modern C++
5367// | | |__ | | | | | | version 3.12.0
5368// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5369//
5370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5371// SPDX-License-Identifier: MIT
5372 
5373 
5374 
5375// #include <nlohmann/detail/macro_scope.hpp>
5376// JSON_HAS_CPP_17
5377#ifdef JSON_HAS_CPP_17
5378 #include <optional> // optional
5379#endif
5380 
5381#include <algorithm> // copy
5382#include <iterator> // begin, end
5383#include <string> // string
5384#include <tuple> // tuple, get
5385#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5386#include <utility> // move, forward, declval, pair
5387#include <valarray> // valarray
5388#include <vector> // vector
5389 
5390// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5391// __ _____ _____ _____
5392// __| | __| | | | JSON for Modern C++
5393// | | |__ | | | | | | version 3.12.0
5394// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5395//
5396// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5397// SPDX-License-Identifier: MIT
5398 
5399 
5400 
5401#include <cstddef> // size_t
5402#include <iterator> // forward_iterator_tag
5403#include <tuple> // tuple_size, get, tuple_element
5404#include <utility> // move
5405 
5406#if JSON_HAS_RANGES
5407 #include <ranges> // enable_borrowed_range
5408#endif
5409 
5410// #include <nlohmann/detail/abi_macros.hpp>
5411 
5412// #include <nlohmann/detail/meta/type_traits.hpp>
5413 
5414// #include <nlohmann/detail/string_utils.hpp>
5415// __ _____ _____ _____
5416// __| | __| | | | JSON for Modern C++
5417// | | |__ | | | | | | version 3.12.0
5418// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5419//
5420// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5421// SPDX-License-Identifier: MIT
5422 
5423 
5424 
5425#include <cstddef> // size_t
5426#include <string> // string, to_string
5427 
5428// #include <nlohmann/detail/abi_macros.hpp>
5429 
5430 
5431NLOHMANN_JSON_NAMESPACE_BEGIN
5432namespace detail
5433{
5434 
5435template<typename StringType>
5436void int_to_string(StringType& target, std::size_t value)
5437{
5438 // For ADL
5439 using std::to_string;
5440 target = to_string(value);
5441}
5442 
5443template<typename StringType>
5444StringType to_string(std::size_t value)
5445{
5446 StringType result;
5447 int_to_string(result, value);
5448 return result;
5449}
5450 
5451} // namespace detail
5452NLOHMANN_JSON_NAMESPACE_END
5453 
5454// #include <nlohmann/detail/value_t.hpp>
5455 
5456 
5457NLOHMANN_JSON_NAMESPACE_BEGIN
5458namespace detail
5459{
5460 
5461template<typename IteratorType> class iteration_proxy_value
5462{
5463 public:
5464 using difference_type = std::ptrdiff_t;
5465 using value_type = iteration_proxy_value;
5466 using pointer = value_type *;
5467 using reference = value_type &;
5468 using iterator_category = std::forward_iterator_tag;
5469 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5470 
5471 private:
5472 /// the iterator
5473 IteratorType anchor{};
5474 /// an index for arrays (used to create key names)
5475 std::size_t array_index = 0;
5476 /// last stringified array index
5477 mutable std::size_t array_index_last = 0;
5478 /// a string representation of the array index
5479 mutable string_type array_index_str = "0";
5480 /// an empty string (to return a reference for primitive values)
5481 string_type empty_str{};
5482 
5483 public:
5484 explicit iteration_proxy_value() = default;
5485 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5486 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5487 && std::is_nothrow_default_constructible<string_type>::value)
5488 : anchor(std::move(it))
5489 , array_index(array_index_)
5490 {}
5491 
5492 iteration_proxy_value(iteration_proxy_value const&) = default;
5493 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5494 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5495 iteration_proxy_value(iteration_proxy_value&&)
5496 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5497 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5498 iteration_proxy_value& operator=(iteration_proxy_value&&)
5499 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5500 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5501 ~iteration_proxy_value() = default;
5502 
5503 /// dereference operator (needed for range-based for)
5504 const iteration_proxy_value& operator*() const
5505 {
5506 return *this;
5507 }
5508 
5509 /// increment operator (needed for range-based for)
5510 iteration_proxy_value& operator++()
5511 {
5512 ++anchor;
5513 ++array_index;
5514 
5515 return *this;
5516 }
5517 
5518 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5519 {
5520 auto tmp = iteration_proxy_value(anchor, array_index);
5521 ++anchor;
5522 ++array_index;
5523 return tmp;
5524 }
5525 
5526 /// equality operator (needed for InputIterator)
5527 bool operator==(const iteration_proxy_value& o) const
5528 {
5529 return anchor == o.anchor;
5530 }
5531 
5532 /// inequality operator (needed for range-based for)
5533 bool operator!=(const iteration_proxy_value& o) const
5534 {
5535 return anchor != o.anchor;
5536 }
5537 
5538 /// return key of the iterator
5539 const string_type& key() const
5540 {
5541 JSON_ASSERT(anchor.m_object != nullptr);
5542 
5543 switch (anchor.m_object->type())
5544 {
5545 // use integer array index as key
5546 case value_t::array:
5547 {
5548 if (array_index != array_index_last)
5549 {
5550 int_to_string( array_index_str, array_index );
5551 array_index_last = array_index;
5552 }
5553 return array_index_str;
5554 }
5555 
5556 // use key from the object
5557 case value_t::object:
5558 return anchor.key();
5559 
5560 // use an empty key for all primitive types
5561 case value_t::null:
5562 case value_t::string:
5563 case value_t::boolean:
5564 case value_t::number_integer:
5565 case value_t::number_unsigned:
5566 case value_t::number_float:
5567 case value_t::binary:
5568 case value_t::discarded:
5569 default:
5570 return empty_str;
5571 }
5572 }
5573 
5574 /// return value of the iterator
5575 typename IteratorType::reference value() const
5576 {
5577 return anchor.value();
5578 }
5579};
5580 
5581/// proxy class for the items() function
5582template<typename IteratorType> class iteration_proxy
5583{
5584 private:
5585 /// the container to iterate
5586 typename IteratorType::pointer container = nullptr;
5587 
5588 public:
5589 explicit iteration_proxy() = default;
5590 
5591 /// construct iteration proxy from a container
5592 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5593 : container(&cont) {}
5594 
5595 iteration_proxy(iteration_proxy const&) = default;
5596 iteration_proxy& operator=(iteration_proxy const&) = default;
5597 iteration_proxy(iteration_proxy&&) noexcept = default;
5598 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5599 ~iteration_proxy() = default;
5600 
5601 /// return iterator begin (needed for range-based for)
5602 iteration_proxy_value<IteratorType> begin() const noexcept
5603 {
5604 return iteration_proxy_value<IteratorType>(container->begin());
5605 }
5606 
5607 /// return iterator end (needed for range-based for)
5608 iteration_proxy_value<IteratorType> end() const noexcept
5609 {
5610 return iteration_proxy_value<IteratorType>(container->end());
5611 }
5612};
5613 
5614// Structured Bindings Support
5615// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5616// And see https://github.com/nlohmann/json/pull/1391
5617template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5618auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5619{
5620 return i.key();
5621}
5622// Structured Bindings Support
5623// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5624// And see https://github.com/nlohmann/json/pull/1391
5625template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5626auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5627{
5628 return i.value();
5629}
5630 
5631} // namespace detail
5632NLOHMANN_JSON_NAMESPACE_END
5633 
5634// The Addition to the STD Namespace is required to add
5635// Structured Bindings Support to the iteration_proxy_value class
5636// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5637// And see https://github.com/nlohmann/json/pull/1391
5638namespace std
5639{
5640 
5641#if defined(__clang__)
5642 // Fix: https://github.com/nlohmann/json/issues/1401
5643 #pragma clang diagnostic push
5644 #pragma clang diagnostic ignored "-Wmismatched-tags"
5645#endif
5646template<typename IteratorType>
5647class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5648 : public std::integral_constant<std::size_t, 2> {};
5649 
5650template<std::size_t N, typename IteratorType>
5651class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5652{
5653 public:
5654 using type = decltype(
5655 get<N>(std::declval <
5656 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5657};
5658#if defined(__clang__)
5659 #pragma clang diagnostic pop
5660#endif
5661 
5662} // namespace std
5663 
5664#if JSON_HAS_RANGES
5665 template <typename IteratorType>
5666 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5667#endif
5668 
5669// #include <nlohmann/detail/meta/cpp_future.hpp>
5670 
5671// #include <nlohmann/detail/meta/std_fs.hpp>
5672 
5673// #include <nlohmann/detail/meta/type_traits.hpp>
5674 
5675// #include <nlohmann/detail/value_t.hpp>
5676 
5677 
5678NLOHMANN_JSON_NAMESPACE_BEGIN
5679namespace detail
5680{
5681 
5682//////////////////
5683// constructors //
5684//////////////////
5685 
5686/*
5687 * Note all external_constructor<>::construct functions need to call
5688 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5689 * allocated value (e.g., a string). See bug issue
5690 * https://github.com/nlohmann/json/issues/2865 for more information.
5691 */
5692 
5693template<value_t> struct external_constructor;
5694 
5695template<>
5696struct external_constructor<value_t::boolean>
5697{
5698 template<typename BasicJsonType>
5699 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5700 {
5701 j.m_data.m_value.destroy(j.m_data.m_type);
5702 j.m_data.m_type = value_t::boolean;
5703 j.m_data.m_value = b;
5704 j.assert_invariant();
5705 }
5706};
5707 
5708template<>
5709struct external_constructor<value_t::string>
5710{
5711 template<typename BasicJsonType>
5712 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5713 {
5714 j.m_data.m_value.destroy(j.m_data.m_type);
5715 j.m_data.m_type = value_t::string;
5716 j.m_data.m_value = s;
5717 j.assert_invariant();
5718 }
5719 
5720 template<typename BasicJsonType>
5721 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5722 {
5723 j.m_data.m_value.destroy(j.m_data.m_type);
5724 j.m_data.m_type = value_t::string;
5725 j.m_data.m_value = std::move(s);
5726 j.assert_invariant();
5727 }
5728 
5729 template < typename BasicJsonType, typename CompatibleStringType,
5730 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5731 int > = 0 >
5732 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5733 {
5734 j.m_data.m_value.destroy(j.m_data.m_type);
5735 j.m_data.m_type = value_t::string;
5736 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5737 j.assert_invariant();
5738 }
5739};
5740 
5741template<>
5742struct external_constructor<value_t::binary>
5743{
5744 template<typename BasicJsonType>
5745 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5746 {
5747 j.m_data.m_value.destroy(j.m_data.m_type);
5748 j.m_data.m_type = value_t::binary;
5749 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5750 j.assert_invariant();
5751 }
5752 
5753 template<typename BasicJsonType>
5754 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5755 {
5756 j.m_data.m_value.destroy(j.m_data.m_type);
5757 j.m_data.m_type = value_t::binary;
5758 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5759 j.assert_invariant();
5760 }
5761};
5762 
5763template<>
5764struct external_constructor<value_t::number_float>
5765{
5766 template<typename BasicJsonType>
5767 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5768 {
5769 j.m_data.m_value.destroy(j.m_data.m_type);
5770 j.m_data.m_type = value_t::number_float;
5771 j.m_data.m_value = val;
5772 j.assert_invariant();
5773 }
5774};
5775 
5776template<>
5777struct external_constructor<value_t::number_unsigned>
5778{
5779 template<typename BasicJsonType>
5780 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5781 {
5782 j.m_data.m_value.destroy(j.m_data.m_type);
5783 j.m_data.m_type = value_t::number_unsigned;
5784 j.m_data.m_value = val;
5785 j.assert_invariant();
5786 }
5787};
5788 
5789template<>
5790struct external_constructor<value_t::number_integer>
5791{
5792 template<typename BasicJsonType>
5793 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5794 {
5795 j.m_data.m_value.destroy(j.m_data.m_type);
5796 j.m_data.m_type = value_t::number_integer;
5797 j.m_data.m_value = val;
5798 j.assert_invariant();
5799 }
5800};
5801 
5802template<>
5803struct external_constructor<value_t::array>
5804{
5805 template<typename BasicJsonType>
5806 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5807 {
5808 j.m_data.m_value.destroy(j.m_data.m_type);
5809 j.m_data.m_type = value_t::array;
5810 j.m_data.m_value = arr;
5811 j.set_parents();
5812 j.assert_invariant();
5813 }
5814 
5815 template<typename BasicJsonType>
5816 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5817 {
5818 j.m_data.m_value.destroy(j.m_data.m_type);
5819 j.m_data.m_type = value_t::array;
5820 j.m_data.m_value = std::move(arr);
5821 j.set_parents();
5822 j.assert_invariant();
5823 }
5824 
5825 template < typename BasicJsonType, typename CompatibleArrayType,
5826 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5827 int > = 0 >
5828 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5829 {
5830 using std::begin;
5831 using std::end;
5832 
5833 j.m_data.m_value.destroy(j.m_data.m_type);
5834 j.m_data.m_type = value_t::array;
5835 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5836 j.set_parents();
5837 j.assert_invariant();
5838 }
5839 
5840 template<typename BasicJsonType>
5841 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5842 {
5843 j.m_data.m_value.destroy(j.m_data.m_type);
5844 j.m_data.m_type = value_t::array;
5845 j.m_data.m_value = value_t::array;
5846 j.m_data.m_value.array->reserve(arr.size());
5847 for (const bool x : arr)
5848 {
5849 j.m_data.m_value.array->push_back(x);
5850 j.set_parent(j.m_data.m_value.array->back());
5851 }
5852 j.assert_invariant();
5853 }
5854 
5855 template<typename BasicJsonType, typename T,
5856 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5857 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5858 {
5859 j.m_data.m_value.destroy(j.m_data.m_type);
5860 j.m_data.m_type = value_t::array;
5861 j.m_data.m_value = value_t::array;
5862 j.m_data.m_value.array->resize(arr.size());
5863 if (arr.size() > 0)
5864 {
5865 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5866 }
5867 j.set_parents();
5868 j.assert_invariant();
5869 }
5870};
5871 
5872template<>
5873struct external_constructor<value_t::object>
5874{
5875 template<typename BasicJsonType>
5876 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5877 {
5878 j.m_data.m_value.destroy(j.m_data.m_type);
5879 j.m_data.m_type = value_t::object;
5880 j.m_data.m_value = obj;
5881 j.set_parents();
5882 j.assert_invariant();
5883 }
5884 
5885 template<typename BasicJsonType>
5886 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5887 {
5888 j.m_data.m_value.destroy(j.m_data.m_type);
5889 j.m_data.m_type = value_t::object;
5890 j.m_data.m_value = std::move(obj);
5891 j.set_parents();
5892 j.assert_invariant();
5893 }
5894 
5895 template < typename BasicJsonType, typename CompatibleObjectType,
5896 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5897 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5898 {
5899 using std::begin;
5900 using std::end;
5901 
5902 j.m_data.m_value.destroy(j.m_data.m_type);
5903 j.m_data.m_type = value_t::object;
5904 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5905 j.set_parents();
5906 j.assert_invariant();
5907 }
5908};
5909 
5910/////////////
5911// to_json //
5912/////////////
5913 
5914#ifdef JSON_HAS_CPP_17
5915template<typename BasicJsonType, typename T,
5916 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5917void to_json(BasicJsonType& j, const std::optional<T>& opt)
5918{
5919 if (opt.has_value())
5920 {
5921 j = *opt;
5922 }
5923 else
5924 {
5925 j = nullptr;
5926 }
5927}
5928#endif
5929 
5930template<typename BasicJsonType, typename T,
5931 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5932inline void to_json(BasicJsonType& j, T b) noexcept
5933{
5934 external_constructor<value_t::boolean>::construct(j, b);
5935}
5936 
5937template < typename BasicJsonType, typename BoolRef,
5938 enable_if_t <
5939 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5940 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5941 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5942 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5943 typename BasicJsonType::boolean_t >::value))
5944 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5945inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5946{
5947 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5948}
5949 
5950template<typename BasicJsonType, typename CompatibleString,
5951 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5952inline void to_json(BasicJsonType& j, const CompatibleString& s)
5953{
5954 external_constructor<value_t::string>::construct(j, s);
5955}
5956 
5957template<typename BasicJsonType>
5958inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5959{
5960 external_constructor<value_t::string>::construct(j, std::move(s));
5961}
5962 
5963template<typename BasicJsonType, typename FloatType,
5964 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5965inline void to_json(BasicJsonType& j, FloatType val) noexcept
5966{
5967 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5968}
5969 
5970template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5971 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5972inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5973{
5974 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5975}
5976 
5977template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5978 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5979inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5980{
5981 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5982}
5983 
5984#if !JSON_DISABLE_ENUM_SERIALIZATION
5985template<typename BasicJsonType, typename EnumType,
5986 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5987inline void to_json(BasicJsonType& j, EnumType e) noexcept
5988{
5989 using underlying_type = typename std::underlying_type<EnumType>::type;
5990 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5991 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5992}
5993#endif // JSON_DISABLE_ENUM_SERIALIZATION
5994 
5995template<typename BasicJsonType>
5996inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5997{
5998 external_constructor<value_t::array>::construct(j, e);
5999}
6000 
6001template < typename BasicJsonType, typename CompatibleArrayType,
6002 enable_if_t < is_compatible_array_type<BasicJsonType,
6003 CompatibleArrayType>::value&&
6004 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6005 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
6006 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6007 !is_basic_json<CompatibleArrayType>::value,
6008 int > = 0 >
6009inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6010{
6011 external_constructor<value_t::array>::construct(j, arr);
6012}
6013 
6014template<typename BasicJsonType>
6015inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6016{
6017 external_constructor<value_t::binary>::construct(j, bin);
6018}
6019 
6020template<typename BasicJsonType, typename T,
6021 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6022inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6023{
6024 external_constructor<value_t::array>::construct(j, std::move(arr));
6025}
6026 
6027template<typename BasicJsonType>
6028inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6029{
6030 external_constructor<value_t::array>::construct(j, std::move(arr));
6031}
6032 
6033template < typename BasicJsonType, typename CompatibleObjectType,
6034 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6035inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6036{
6037 external_constructor<value_t::object>::construct(j, obj);
6038}
6039 
6040template<typename BasicJsonType>
6041inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6042{
6043 external_constructor<value_t::object>::construct(j, std::move(obj));
6044}
6045 
6046template <
6047 typename BasicJsonType, typename T, std::size_t N,
6048 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6049 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6050 int > = 0 >
6051inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6052{
6053 external_constructor<value_t::array>::construct(j, arr);
6054}
6055 
6056template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6057inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6058{
6059 j = { p.first, p.second };
6060}
6061 
6062// for https://github.com/nlohmann/json/pull/1134
6063template<typename BasicJsonType, typename T,
6064 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
6065inline void to_json(BasicJsonType& j, const T& b)
6066{
6067 j = { {b.key(), b.value()} };
6068}
6069 
6070template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6071inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6072{
6073 j = { std::get<Idx>(t)... };
6074}
6075 
6076template<typename BasicJsonType, typename Tuple>
6077inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6078{
6079 using array_t = typename BasicJsonType::array_t;
6080 j = array_t();
6081}
6082 
6083template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6084inline void to_json(BasicJsonType& j, const T& t)
6085{
6086 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6087}
6088 
6089#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6090template<typename BasicJsonType>
6091inline void to_json(BasicJsonType& j, const std_fs::path& p)
6092{
6093#ifdef JSON_HAS_CPP_20
6094 const std::u8string s = p.u8string();
6095 j = std::string(s.begin(), s.end());
6096#else
6097 j = p.u8string(); // returns std::string in C++17
6098#endif
6099}
6100#endif
6101 
6102struct to_json_fn
6103{
6104 template<typename BasicJsonType, typename T>
6105 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6106 -> decltype(to_json(j, std::forward<T>(val)), void())
6107 {
6108 return to_json(j, std::forward<T>(val));
6109 }
6110};
6111} // namespace detail
6112 
6113#ifndef JSON_HAS_CPP_17
6114/// namespace to hold default `to_json` function
6115/// to see why this is required:
6116/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
6117namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6118{
6119#endif
6120JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6121 detail::static_const<detail::to_json_fn>::value;
6122#ifndef JSON_HAS_CPP_17
6123} // namespace
6124#endif
6125 
6126NLOHMANN_JSON_NAMESPACE_END
6127 
6128// #include <nlohmann/detail/meta/identity_tag.hpp>
6129 
6130 
6131NLOHMANN_JSON_NAMESPACE_BEGIN
6132 
6133/// @sa https://json.nlohmann.me/api/adl_serializer/
6134template<typename ValueType, typename>
6135struct adl_serializer
6136{
6137 /// @brief convert a JSON value to any value type
6138 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
6139 template<typename BasicJsonType, typename TargetType = ValueType>
6140 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6141 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6142 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6143 {
6144 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6145 }
6146 
6147 /// @brief convert a JSON value to any value type
6148 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
6149 template<typename BasicJsonType, typename TargetType = ValueType>
6150 static auto from_json(BasicJsonType && j) noexcept(
6151 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6152 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6153 {
6154 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6155 }
6156 
6157 /// @brief convert any value type to a JSON value
6158 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
6159 template<typename BasicJsonType, typename TargetType = ValueType>
6160 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6161 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6162 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6163 {
6164 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6165 }
6166};
6167 
6168NLOHMANN_JSON_NAMESPACE_END
6169 
6170// #include <nlohmann/byte_container_with_subtype.hpp>
6171// __ _____ _____ _____
6172// __| | __| | | | JSON for Modern C++
6173// | | |__ | | | | | | version 3.12.0
6174// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6175//
6176// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6177// SPDX-License-Identifier: MIT
6178 
6179 
6180 
6181#include <cstdint> // uint8_t, uint64_t
6182#include <tuple> // tie
6183#include <utility> // move
6184 
6185// #include <nlohmann/detail/abi_macros.hpp>
6186 
6187 
6188NLOHMANN_JSON_NAMESPACE_BEGIN
6189 
6190/// @brief an internal type for a backed binary type
6191/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
6192template<typename BinaryType>
6193class byte_container_with_subtype : public BinaryType
6194{
6195 public:
6196 using container_type = BinaryType;
6197 using subtype_type = std::uint64_t;
6198 
6199 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6200 byte_container_with_subtype() noexcept(noexcept(container_type()))
6201 : container_type()
6202 {}
6203 
6204 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6205 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
6206 : container_type(b)
6207 {}
6208 
6209 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6210 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6211 : container_type(std::move(b))
6212 {}
6213 
6214 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6215 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
6216 : container_type(b)
6217 , m_subtype(subtype_)
6218 , m_has_subtype(true)
6219 {}
6220 
6221 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6222 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6223 : container_type(std::move(b))
6224 , m_subtype(subtype_)
6225 , m_has_subtype(true)
6226 {}
6227 
6228 bool operator==(const byte_container_with_subtype& rhs) const
6229 {
6230 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6231 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6232 }
6233 
6234 bool operator!=(const byte_container_with_subtype& rhs) const
6235 {
6236 return !(rhs == *this);
6237 }
6238 
6239 /// @brief sets the binary subtype
6240 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
6241 void set_subtype(subtype_type subtype_) noexcept
6242 {
6243 m_subtype = subtype_;
6244 m_has_subtype = true;
6245 }
6246 
6247 /// @brief return the binary subtype
6248 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
6249 constexpr subtype_type subtype() const noexcept
6250 {
6251 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6252 }
6253 
6254 /// @brief return whether the value has a subtype
6255 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
6256 constexpr bool has_subtype() const noexcept
6257 {
6258 return m_has_subtype;
6259 }
6260 
6261 /// @brief clears the binary subtype
6262 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
6263 void clear_subtype() noexcept
6264 {
6265 m_subtype = 0;
6266 m_has_subtype = false;
6267 }
6268 
6269 private:
6270 subtype_type m_subtype = 0;
6271 bool m_has_subtype = false;
6272};
6273 
6274NLOHMANN_JSON_NAMESPACE_END
6275 
6276// #include <nlohmann/detail/conversions/from_json.hpp>
6277 
6278// #include <nlohmann/detail/conversions/to_json.hpp>
6279 
6280// #include <nlohmann/detail/exceptions.hpp>
6281 
6282// #include <nlohmann/detail/hash.hpp>
6283// __ _____ _____ _____
6284// __| | __| | | | JSON for Modern C++
6285// | | |__ | | | | | | version 3.12.0
6286// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6287//
6288// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6289// SPDX-License-Identifier: MIT
6290 
6291 
6292 
6293#include <cstdint> // uint8_t
6294#include <cstddef> // size_t
6295#include <functional> // hash
6296 
6297// #include <nlohmann/detail/abi_macros.hpp>
6298 
6299// #include <nlohmann/detail/value_t.hpp>
6300 
6301 
6302NLOHMANN_JSON_NAMESPACE_BEGIN
6303namespace detail
6304{
6305 
6306// boost::hash_combine
6307inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6308{
6309 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6310 return seed;
6311}
6312 
6313/*!
6314@brief hash a JSON value
6315 
6316The hash function tries to rely on std::hash where possible. Furthermore, the
6317type of the JSON value is taken into account to have different hash values for
6318null, 0, 0U, and false, etc.
6319 
6320@tparam BasicJsonType basic_json specialization
6321@param j JSON value to hash
6322@return hash value of j
6323*/
6324template<typename BasicJsonType>
6325std::size_t hash(const BasicJsonType& j)
6326{
6327 using string_t = typename BasicJsonType::string_t;
6328 using number_integer_t = typename BasicJsonType::number_integer_t;
6329 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6330 using number_float_t = typename BasicJsonType::number_float_t;
6331 
6332 const auto type = static_cast<std::size_t>(j.type());
6333 switch (j.type())
6334 {
6335 case BasicJsonType::value_t::null:
6336 case BasicJsonType::value_t::discarded:
6337 {
6338 return combine(type, 0);
6339 }
6340 
6341 case BasicJsonType::value_t::object:
6342 {
6343 auto seed = combine(type, j.size());
6344 for (const auto& element : j.items())
6345 {
6346 const auto h = std::hash<string_t> {}(element.key());
6347 seed = combine(seed, h);
6348 seed = combine(seed, hash(element.value()));
6349 }
6350 return seed;
6351 }
6352 
6353 case BasicJsonType::value_t::array:
6354 {
6355 auto seed = combine(type, j.size());
6356 for (const auto& element : j)
6357 {
6358 seed = combine(seed, hash(element));
6359 }
6360 return seed;
6361 }
6362 
6363 case BasicJsonType::value_t::string:
6364 {
6365 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6366 return combine(type, h);
6367 }
6368 
6369 case BasicJsonType::value_t::boolean:
6370 {
6371 const auto h = std::hash<bool> {}(j.template get<bool>());
6372 return combine(type, h);
6373 }
6374 
6375 case BasicJsonType::value_t::number_integer:
6376 {
6377 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6378 return combine(type, h);
6379 }
6380 
6381 case BasicJsonType::value_t::number_unsigned:
6382 {
6383 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6384 return combine(type, h);
6385 }
6386 
6387 case BasicJsonType::value_t::number_float:
6388 {
6389 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6390 return combine(type, h);
6391 }
6392 
6393 case BasicJsonType::value_t::binary:
6394 {
6395 auto seed = combine(type, j.get_binary().size());
6396 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6397 seed = combine(seed, h);
6398 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6399 for (const auto byte : j.get_binary())
6400 {
6401 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6402 }
6403 return seed;
6404 }
6405 
6406 default: // LCOV_EXCL_LINE
6407 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6408 return 0; // LCOV_EXCL_LINE
6409 }
6410}
6411 
6412} // namespace detail
6413NLOHMANN_JSON_NAMESPACE_END
6414 
6415// #include <nlohmann/detail/input/binary_reader.hpp>
6416// __ _____ _____ _____
6417// __| | __| | | | JSON for Modern C++
6418// | | |__ | | | | | | version 3.12.0
6419// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6420//
6421// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6422// SPDX-License-Identifier: MIT
6423 
6424 
6425 
6426#include <algorithm> // generate_n
6427#include <array> // array
6428#include <cmath> // ldexp
6429#include <cstddef> // size_t
6430#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6431#include <cstdio> // snprintf
6432#include <cstring> // memcpy
6433#include <iterator> // back_inserter
6434#include <limits> // numeric_limits
6435#include <string> // char_traits, string
6436#include <utility> // make_pair, move
6437#include <vector> // vector
6438#ifdef __cpp_lib_byteswap
6439 #include <bit> //byteswap
6440#endif
6441 
6442// #include <nlohmann/detail/exceptions.hpp>
6443 
6444// #include <nlohmann/detail/input/input_adapters.hpp>
6445// __ _____ _____ _____
6446// __| | __| | | | JSON for Modern C++
6447// | | |__ | | | | | | version 3.12.0
6448// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6449//
6450// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6451// SPDX-License-Identifier: MIT
6452 
6453 
6454 
6455#include <array> // array
6456#include <cstddef> // size_t
6457#include <cstring> // strlen
6458#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6459#include <memory> // shared_ptr, make_shared, addressof
6460#include <numeric> // accumulate
6461#include <string> // string, char_traits
6462#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6463#include <utility> // pair, declval
6464 
6465#ifndef JSON_NO_IO
6466 #include <cstdio> // FILE *
6467 #include <istream> // istream
6468#endif // JSON_NO_IO
6469 
6470// #include <nlohmann/detail/exceptions.hpp>
6471 
6472// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6473 
6474// #include <nlohmann/detail/macro_scope.hpp>
6475 
6476// #include <nlohmann/detail/meta/type_traits.hpp>
6477 
6478 
6479NLOHMANN_JSON_NAMESPACE_BEGIN
6480namespace detail
6481{
6482 
6483/// the supported input formats
6484enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6485 
6486////////////////////
6487// input adapters //
6488////////////////////
6489 
6490#ifndef JSON_NO_IO
6491/*!
6492Input adapter for stdio file access. This adapter read only 1 byte and do not use any
6493 buffer. This adapter is a very low level adapter.
6494*/
6495class file_input_adapter
6496{
6497 public:
6498 using char_type = char;
6499 
6500 JSON_HEDLEY_NON_NULL(2)
6501 explicit file_input_adapter(std::FILE* f) noexcept
6502 : m_file(f)
6503 {
6504 JSON_ASSERT(m_file != nullptr);
6505 }
6506 
6507 // make class move-only
6508 file_input_adapter(const file_input_adapter&) = delete;
6509 file_input_adapter(file_input_adapter&&) noexcept = default;
6510 file_input_adapter& operator=(const file_input_adapter&) = delete;
6511 file_input_adapter& operator=(file_input_adapter&&) = delete;
6512 ~file_input_adapter() = default;
6513 
6514 std::char_traits<char>::int_type get_character() noexcept
6515 {
6516 return std::fgetc(m_file);
6517 }
6518 
6519 // returns the number of characters successfully read
6520 template<class T>
6521 std::size_t get_elements(T* dest, std::size_t count = 1)
6522 {
6523 return fread(dest, 1, sizeof(T) * count, m_file);
6524 }
6525 
6526 private:
6527 /// the file pointer to read from
6528 std::FILE* m_file;
6529};
6530 
6531/*!
6532Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
6533beginning of input. Does not support changing the underlying std::streambuf
6534in mid-input. Maintains underlying std::istream and std::streambuf to support
6535subsequent use of standard std::istream operations to process any input
6536characters following those used in parsing the JSON input. Clears the
6537std::istream flags; any input errors (e.g., EOF) will be detected by the first
6538subsequent call for input from the std::istream.
6539*/
6540class input_stream_adapter
6541{
6542 public:
6543 using char_type = char;
6544 
6545 ~input_stream_adapter()
6546 {
6547 // clear stream flags; we use underlying streambuf I/O, do not
6548 // maintain ifstream flags, except eof
6549 if (is != nullptr)
6550 {
6551 is->clear(is->rdstate() & std::ios::eofbit);
6552 }
6553 }
6554 
6555 explicit input_stream_adapter(std::istream& i)
6556 : is(&i), sb(i.rdbuf())
6557 {}
6558 
6559 // delete because of pointer members
6560 input_stream_adapter(const input_stream_adapter&) = delete;
6561 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6562 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6563 
6564 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6565 : is(rhs.is), sb(rhs.sb)
6566 {
6567 rhs.is = nullptr;
6568 rhs.sb = nullptr;
6569 }
6570 
6571 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6572 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6573 // end up as the same value, e.g. 0xFFFFFFFF.
6574 std::char_traits<char>::int_type get_character()
6575 {
6576 auto res = sb->sbumpc();
6577 // set eof manually, as we don't use the istream interface.
6578 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6579 {
6580 is->clear(is->rdstate() | std::ios::eofbit);
6581 }
6582 return res;
6583 }
6584 
6585 template<class T>
6586 std::size_t get_elements(T* dest, std::size_t count = 1)
6587 {
6588 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6589 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6590 {
6591 is->clear(is->rdstate() | std::ios::eofbit);
6592 }
6593 return res;
6594 }
6595 
6596 private:
6597 /// the associated input stream
6598 std::istream* is = nullptr;
6599 std::streambuf* sb = nullptr;
6600};
6601#endif // JSON_NO_IO
6602 
6603// General-purpose iterator-based adapter. It might not be as fast as
6604// theoretically possible for some containers, but it is extremely versatile.
6605template<typename IteratorType>
6606class iterator_input_adapter
6607{
6608 public:
6609 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6610 
6611 iterator_input_adapter(IteratorType first, IteratorType last)
6612 : current(std::move(first)), end(std::move(last))
6613 {}
6614 
6615 typename char_traits<char_type>::int_type get_character()
6616 {
6617 if (JSON_HEDLEY_LIKELY(current != end))
6618 {
6619 auto result = char_traits<char_type>::to_int_type(*current);
6620 std::advance(current, 1);
6621 return result;
6622 }
6623 
6624 return char_traits<char_type>::eof();
6625 }
6626 
6627 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6628 template<class T>
6629 std::size_t get_elements(T* dest, std::size_t count = 1)
6630 {
6631 auto* ptr = reinterpret_cast<char*>(dest);
6632 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6633 {
6634 if (JSON_HEDLEY_LIKELY(current != end))
6635 {
6636 ptr[read_index] = static_cast<char>(*current);
6637 std::advance(current, 1);
6638 }
6639 else
6640 {
6641 return read_index;
6642 }
6643 }
6644 return count * sizeof(T);
6645 }
6646 
6647 private:
6648 IteratorType current;
6649 IteratorType end;
6650 
6651 template<typename BaseInputAdapter, size_t T>
6652 friend struct wide_string_input_helper;
6653 
6654 bool empty() const
6655 {
6656 return current == end;
6657 }
6658};
6659 
6660template<typename BaseInputAdapter, size_t T>
6661struct wide_string_input_helper;
6662 
6663template<typename BaseInputAdapter>
6664struct wide_string_input_helper<BaseInputAdapter, 4>
6665{
6666 // UTF-32
6667 static void fill_buffer(BaseInputAdapter& input,
6668 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6669 size_t& utf8_bytes_index,
6670 size_t& utf8_bytes_filled)
6671 {
6672 utf8_bytes_index = 0;
6673 
6674 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6675 {
6676 utf8_bytes[0] = std::char_traits<char>::eof();
6677 utf8_bytes_filled = 1;
6678 }
6679 else
6680 {
6681 // get the current character
6682 const auto wc = input.get_character();
6683 
6684 // UTF-32 to UTF-8 encoding
6685 if (wc < 0x80)
6686 {
6687 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6688 utf8_bytes_filled = 1;
6689 }
6690 else if (wc <= 0x7FF)
6691 {
6692 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6693 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6694 utf8_bytes_filled = 2;
6695 }
6696 else if (wc <= 0xFFFF)
6697 {
6698 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6699 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6700 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6701 utf8_bytes_filled = 3;
6702 }
6703 else if (wc <= 0x10FFFF)
6704 {
6705 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6706 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6707 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6708 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6709 utf8_bytes_filled = 4;
6710 }
6711 else
6712 {
6713 // unknown character
6714 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6715 utf8_bytes_filled = 1;
6716 }
6717 }
6718 }
6719};
6720 
6721template<typename BaseInputAdapter>
6722struct wide_string_input_helper<BaseInputAdapter, 2>
6723{
6724 // UTF-16
6725 static void fill_buffer(BaseInputAdapter& input,
6726 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6727 size_t& utf8_bytes_index,
6728 size_t& utf8_bytes_filled)
6729 {
6730 utf8_bytes_index = 0;
6731 
6732 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6733 {
6734 utf8_bytes[0] = std::char_traits<char>::eof();
6735 utf8_bytes_filled = 1;
6736 }
6737 else
6738 {
6739 // get the current character
6740 const auto wc = input.get_character();
6741 
6742 // UTF-16 to UTF-8 encoding
6743 if (wc < 0x80)
6744 {
6745 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6746 utf8_bytes_filled = 1;
6747 }
6748 else if (wc <= 0x7FF)
6749 {
6750 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6751 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6752 utf8_bytes_filled = 2;
6753 }
6754 else if (0xD800 > wc || wc >= 0xE000)
6755 {
6756 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6757 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6758 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6759 utf8_bytes_filled = 3;
6760 }
6761 else
6762 {
6763 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6764 {
6765 const auto wc2 = static_cast<unsigned int>(input.get_character());
6766 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6767 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6768 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6769 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6770 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6771 utf8_bytes_filled = 4;
6772 }
6773 else
6774 {
6775 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6776 utf8_bytes_filled = 1;
6777 }
6778 }
6779 }
6780 }
6781};
6782 
6783// Wraps another input adapter to convert wide character types into individual bytes.
6784template<typename BaseInputAdapter, typename WideCharType>
6785class wide_string_input_adapter
6786{
6787 public:
6788 using char_type = char;
6789 
6790 wide_string_input_adapter(BaseInputAdapter base)
6791 : base_adapter(base) {}
6792 
6793 typename std::char_traits<char>::int_type get_character() noexcept
6794 {
6795 // check if buffer needs to be filled
6796 if (utf8_bytes_index == utf8_bytes_filled)
6797 {
6798 fill_buffer<sizeof(WideCharType)>();
6799 
6800 JSON_ASSERT(utf8_bytes_filled > 0);
6801 JSON_ASSERT(utf8_bytes_index == 0);
6802 }
6803 
6804 // use buffer
6805 JSON_ASSERT(utf8_bytes_filled > 0);
6806 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6807 return utf8_bytes[utf8_bytes_index++];
6808 }
6809 
6810 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6811 template<class T>
6812 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6813 {
6814 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6815 }
6816 
6817 private:
6818 BaseInputAdapter base_adapter;
6819 
6820 template<size_t T>
6821 void fill_buffer()
6822 {
6823 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6824 }
6825 
6826 /// a buffer for UTF-8 bytes
6827 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6828 
6829 /// index to the utf8_codes array for the next valid byte
6830 std::size_t utf8_bytes_index = 0;
6831 /// number of valid bytes in the utf8_codes array
6832 std::size_t utf8_bytes_filled = 0;
6833};
6834 
6835template<typename IteratorType, typename Enable = void>
6836struct iterator_input_adapter_factory
6837{
6838 using iterator_type = IteratorType;
6839 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6840 using adapter_type = iterator_input_adapter<iterator_type>;
6841 
6842 static adapter_type create(IteratorType first, IteratorType last)
6843 {
6844 return adapter_type(std::move(first), std::move(last));
6845 }
6846};
6847 
6848template<typename T>
6849struct is_iterator_of_multibyte
6850{
6851 using value_type = typename std::iterator_traits<T>::value_type;
6852 enum
6853 {
6854 value = sizeof(value_type) > 1
6855 };
6856};
6857 
6858template<typename IteratorType>
6859struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6860{
6861 using iterator_type = IteratorType;
6862 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6863 using base_adapter_type = iterator_input_adapter<iterator_type>;
6864 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6865 
6866 static adapter_type create(IteratorType first, IteratorType last)
6867 {
6868 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6869 }
6870};
6871 
6872// General purpose iterator-based input
6873template<typename IteratorType>
6874typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6875{
6876 using factory_type = iterator_input_adapter_factory<IteratorType>;
6877 return factory_type::create(first, last);
6878}
6879 
6880// Convenience shorthand from container to iterator
6881// Enables ADL on begin(container) and end(container)
6882// Encloses the using declarations in namespace for not to leak them to outside scope
6883 
6884namespace container_input_adapter_factory_impl
6885{
6886 
6887using std::begin;
6888using std::end;
6889 
6890template<typename ContainerType, typename Enable = void>
6891struct container_input_adapter_factory {};
6892 
6893template<typename ContainerType>
6894struct container_input_adapter_factory< ContainerType,
6895 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6896 {
6897 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6898 
6899 static adapter_type create(const ContainerType& container)
6900{
6901 return input_adapter(begin(container), end(container));
6902}
6903 };
6904 
6905} // namespace container_input_adapter_factory_impl
6906 
6907template<typename ContainerType>
6908typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6909{
6910 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6911}
6912 
6913// specialization for std::string
6914using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6915 
6916#ifndef JSON_NO_IO
6917// Special cases with fast paths
6918inline file_input_adapter input_adapter(std::FILE* file)
6919{
6920 if (file == nullptr)
6921 {
6922 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6923 }
6924 return file_input_adapter(file);
6925}
6926 
6927inline input_stream_adapter input_adapter(std::istream& stream)
6928{
6929 return input_stream_adapter(stream);
6930}
6931 
6932inline input_stream_adapter input_adapter(std::istream&& stream)
6933{
6934 return input_stream_adapter(stream);
6935}
6936#endif // JSON_NO_IO
6937 
6938using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6939 
6940// Null-delimited strings, and the like.
6941template < typename CharT,
6942 typename std::enable_if <
6943 std::is_pointer<CharT>::value&&
6944 !std::is_array<CharT>::value&&
6945 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6946 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6947 int >::type = 0 >
6948contiguous_bytes_input_adapter input_adapter(CharT b)
6949{
6950 if (b == nullptr)
6951 {
6952 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6953 }
6954 auto length = std::strlen(reinterpret_cast<const char*>(b));
6955 const auto* ptr = reinterpret_cast<const char*>(b);
6956 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
6957}
6958 
6959template<typename T, std::size_t N>
6960auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6961{
6962 return input_adapter(array, array + N);
6963}
6964 
6965// This class only handles inputs of input_buffer_adapter type.
6966// It's required so that expressions like {ptr, len} can be implicitly cast
6967// to the correct adapter.
6968class span_input_adapter
6969{
6970 public:
6971 template < typename CharT,
6972 typename std::enable_if <
6973 std::is_pointer<CharT>::value&&
6974 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6975 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6976 int >::type = 0 >
6977 span_input_adapter(CharT b, std::size_t l)
6978 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6979 
6980 template<class IteratorType,
6981 typename std::enable_if<
6982 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6983 int>::type = 0>
6984 span_input_adapter(IteratorType first, IteratorType last)
6985 : ia(input_adapter(first, last)) {}
6986 
6987 contiguous_bytes_input_adapter&& get()
6988 {
6989 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6990 }
6991 
6992 private:
6993 contiguous_bytes_input_adapter ia;
6994};
6995 
6996} // namespace detail
6997NLOHMANN_JSON_NAMESPACE_END
6998 
6999// #include <nlohmann/detail/input/json_sax.hpp>
7000// __ _____ _____ _____
7001// __| | __| | | | JSON for Modern C++
7002// | | |__ | | | | | | version 3.12.0
7003// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7004//
7005// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7006// SPDX-License-Identifier: MIT
7007 
7008 
7009 
7010#include <cstddef>
7011#include <string> // string
7012#include <type_traits> // enable_if_t
7013#include <utility> // move
7014#include <vector> // vector
7015 
7016// #include <nlohmann/detail/exceptions.hpp>
7017 
7018// #include <nlohmann/detail/input/lexer.hpp>
7019// __ _____ _____ _____
7020// __| | __| | | | JSON for Modern C++
7021// | | |__ | | | | | | version 3.12.0
7022// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7023//
7024// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7025// SPDX-License-Identifier: MIT
7026 
7027 
7028 
7029#include <array> // array
7030#include <clocale> // localeconv
7031#include <cstddef> // size_t
7032#include <cstdio> // snprintf
7033#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7034#include <initializer_list> // initializer_list
7035#include <string> // char_traits, string
7036#include <utility> // move
7037#include <vector> // vector
7038 
7039// #include <nlohmann/detail/input/input_adapters.hpp>
7040 
7041// #include <nlohmann/detail/input/position_t.hpp>
7042 
7043// #include <nlohmann/detail/macro_scope.hpp>
7044 
7045// #include <nlohmann/detail/meta/type_traits.hpp>
7046 
7047 
7048NLOHMANN_JSON_NAMESPACE_BEGIN
7049namespace detail
7050{
7051 
7052///////////
7053// lexer //
7054///////////
7055 
7056template<typename BasicJsonType>
7057class lexer_base
7058{
7059 public:
7060 /// token types for the parser
7061 enum class token_type
7062 {
7063 uninitialized, ///< indicating the scanner is uninitialized
7064 literal_true, ///< the `true` literal
7065 literal_false, ///< the `false` literal
7066 literal_null, ///< the `null` literal
7067 value_string, ///< a string -- use get_string() for actual value
7068 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7069 value_integer, ///< a signed integer -- use get_number_integer() for actual value
7070 value_float, ///< an floating point number -- use get_number_float() for actual value
7071 begin_array, ///< the character for array begin `[`
7072 begin_object, ///< the character for object begin `{`
7073 end_array, ///< the character for array end `]`
7074 end_object, ///< the character for object end `}`
7075 name_separator, ///< the name separator `:`
7076 value_separator, ///< the value separator `,`
7077 parse_error, ///< indicating a parse error
7078 end_of_input, ///< indicating the end of the input buffer
7079 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7080 };
7081 
7082 /// return name of values of type token_type (only used for errors)
7083 JSON_HEDLEY_RETURNS_NON_NULL
7084 JSON_HEDLEY_CONST
7085 static const char* token_type_name(const token_type t) noexcept
7086 {
7087 switch (t)
7088 {
7089 case token_type::uninitialized:
7090 return "<uninitialized>";
7091 case token_type::literal_true:
7092 return "true literal";
7093 case token_type::literal_false:
7094 return "false literal";
7095 case token_type::literal_null:
7096 return "null literal";
7097 case token_type::value_string:
7098 return "string literal";
7099 case token_type::value_unsigned:
7100 case token_type::value_integer:
7101 case token_type::value_float:
7102 return "number literal";
7103 case token_type::begin_array:
7104 return "'['";
7105 case token_type::begin_object:
7106 return "'{'";
7107 case token_type::end_array:
7108 return "']'";
7109 case token_type::end_object:
7110 return "'}'";
7111 case token_type::name_separator:
7112 return "':'";
7113 case token_type::value_separator:
7114 return "','";
7115 case token_type::parse_error:
7116 return "<parse error>";
7117 case token_type::end_of_input:
7118 return "end of input";
7119 case token_type::literal_or_value:
7120 return "'[', '{', or a literal";
7121 // LCOV_EXCL_START
7122 default: // catch non-enum values
7123 return "unknown token";
7124 // LCOV_EXCL_STOP
7125 }
7126 }
7127};
7128/*!
7129@brief lexical analysis
7130 
7131This class organizes the lexical analysis during JSON deserialization.
7132*/
7133template<typename BasicJsonType, typename InputAdapterType>
7134class lexer : public lexer_base<BasicJsonType>
7135{
7136 using number_integer_t = typename BasicJsonType::number_integer_t;
7137 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7138 using number_float_t = typename BasicJsonType::number_float_t;
7139 using string_t = typename BasicJsonType::string_t;
7140 using char_type = typename InputAdapterType::char_type;
7141 using char_int_type = typename char_traits<char_type>::int_type;
7142 
7143 public:
7144 using token_type = typename lexer_base<BasicJsonType>::token_type;
7145 
7146 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7147 : ia(std::move(adapter))
7148 , ignore_comments(ignore_comments_)
7149 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7150 {}
7151 
7152 // delete because of pointer members
7153 lexer(const lexer&) = delete;
7154 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7155 lexer& operator=(lexer&) = delete;
7156 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7157 ~lexer() = default;
7158 
7159 private:
7160 /////////////////////
7161 // locales
7162 /////////////////////
7163 
7164 /// return the locale-dependent decimal point
7165 JSON_HEDLEY_PURE
7166 static char get_decimal_point() noexcept
7167 {
7168 const auto* loc = localeconv();
7169 JSON_ASSERT(loc != nullptr);
7170 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7171 }
7172 
7173 /////////////////////
7174 // scan functions
7175 /////////////////////
7176 
7177 /*!
7178 @brief get codepoint from 4 hex characters following `\u`
7179 
7180 For input "\u c1 c2 c3 c4" the codepoint is:
7181 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
7182 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
7183 
7184 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
7185 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
7186 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
7187 between the ASCII value of the character and the desired integer value.
7188 
7189 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
7190 non-hex character)
7191 */
7192 int get_codepoint()
7193 {
7194 // this function only makes sense after reading `\u`
7195 JSON_ASSERT(current == 'u');
7196 int codepoint = 0;
7197 
7198 const auto factors = { 12u, 8u, 4u, 0u };
7199 for (const auto factor : factors)
7200 {
7201 get();
7202 
7203 if (current >= '0' && current <= '9')
7204 {
7205 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7206 }
7207 else if (current >= 'A' && current <= 'F')
7208 {
7209 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7210 }
7211 else if (current >= 'a' && current <= 'f')
7212 {
7213 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7214 }
7215 else
7216 {
7217 return -1;
7218 }
7219 }
7220 
7221 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7222 return codepoint;
7223 }
7224 
7225 /*!
7226 @brief check if the next byte(s) are inside a given range
7227 
7228 Adds the current byte and, for each passed range, reads a new byte and
7229 checks if it is inside the range. If a violation was detected, set up an
7230 error message and return false. Otherwise, return true.
7231 
7232 @param[in] ranges list of integers; interpreted as list of pairs of
7233 inclusive lower and upper bound, respectively
7234 
7235 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
7236 1, 2, or 3 pairs. This precondition is enforced by an assertion.
7237 
7238 @return true if and only if no range violation was detected
7239 */
7240 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7241 {
7242 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7243 add(current);
7244 
7245 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7246 {
7247 get();
7248 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7249 {
7250 add(current);
7251 }
7252 else
7253 {
7254 error_message = "invalid string: ill-formed UTF-8 byte";
7255 return false;
7256 }
7257 }
7258 
7259 return true;
7260 }
7261 
7262 /*!
7263 @brief scan a string literal
7264 
7265 This function scans a string according to Sect. 7 of RFC 8259. While
7266 scanning, bytes are escaped and copied into buffer token_buffer. Then the
7267 function returns successfully, token_buffer is *not* null-terminated (as it
7268 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
7269 string.
7270 
7271 @return token_type::value_string if string could be successfully scanned,
7272 token_type::parse_error otherwise
7273 
7274 @note In case of errors, variable error_message contains a textual
7275 description.
7276 */
7277 token_type scan_string()
7278 {
7279 // reset token_buffer (ignore opening quote)
7280 reset();
7281 
7282 // we entered the function by reading an open quote
7283 JSON_ASSERT(current == '\"');
7284 
7285 while (true)
7286 {
7287 // get next character
7288 switch (get())
7289 {
7290 // end of file while parsing string
7291 case char_traits<char_type>::eof():
7292 {
7293 error_message = "invalid string: missing closing quote";
7294 return token_type::parse_error;
7295 }
7296 
7297 // closing quote
7298 case '\"':
7299 {
7300 return token_type::value_string;
7301 }
7302 
7303 // escapes
7304 case '\\':
7305 {
7306 switch (get())
7307 {
7308 // quotation mark
7309 case '\"':
7310 add('\"');
7311 break;
7312 // reverse solidus
7313 case '\\':
7314 add('\\');
7315 break;
7316 // solidus
7317 case '/':
7318 add('/');
7319 break;
7320 // backspace
7321 case 'b':
7322 add('\b');
7323 break;
7324 // form feed
7325 case 'f':
7326 add('\f');
7327 break;
7328 // line feed
7329 case 'n':
7330 add('\n');
7331 break;
7332 // carriage return
7333 case 'r':
7334 add('\r');
7335 break;
7336 // tab
7337 case 't':
7338 add('\t');
7339 break;
7340 
7341 // unicode escapes
7342 case 'u':
7343 {
7344 const int codepoint1 = get_codepoint();
7345 int codepoint = codepoint1; // start with codepoint1
7346 
7347 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7348 {
7349 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7350 return token_type::parse_error;
7351 }
7352 
7353 // check if code point is a high surrogate
7354 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7355 {
7356 // expect next \uxxxx entry
7357 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7358 {
7359 const int codepoint2 = get_codepoint();
7360 
7361 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7362 {
7363 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7364 return token_type::parse_error;
7365 }
7366 
7367 // check if codepoint2 is a low surrogate
7368 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7369 {
7370 // overwrite codepoint
7371 codepoint = static_cast<int>(
7372 // high surrogate occupies the most significant 22 bits
7373 (static_cast<unsigned int>(codepoint1) << 10u)
7374 // low surrogate occupies the least significant 15 bits
7375 + static_cast<unsigned int>(codepoint2)
7376 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7377 // in the result, so we have to subtract with:
7378 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7379 - 0x35FDC00u);
7380 }
7381 else
7382 {
7383 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7384 return token_type::parse_error;
7385 }
7386 }
7387 else
7388 {
7389 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7390 return token_type::parse_error;
7391 }
7392 }
7393 else
7394 {
7395 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7396 {
7397 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7398 return token_type::parse_error;
7399 }
7400 }
7401 
7402 // result of the above calculation yields a proper codepoint
7403 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7404 
7405 // translate codepoint into bytes
7406 if (codepoint < 0x80)
7407 {
7408 // 1-byte characters: 0xxxxxxx (ASCII)
7409 add(static_cast<char_int_type>(codepoint));
7410 }
7411 else if (codepoint <= 0x7FF)
7412 {
7413 // 2-byte characters: 110xxxxx 10xxxxxx
7414 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7415 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7416 }
7417 else if (codepoint <= 0xFFFF)
7418 {
7419 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7420 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7421 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7422 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7423 }
7424 else
7425 {
7426 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7427 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7428 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7429 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7430 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7431 }
7432 
7433 break;
7434 }
7435 
7436 // other characters after escape
7437 default:
7438 error_message = "invalid string: forbidden character after backslash";
7439 return token_type::parse_error;
7440 }
7441 
7442 break;
7443 }
7444 
7445 // invalid control characters
7446 case 0x00:
7447 {
7448 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7449 return token_type::parse_error;
7450 }
7451 
7452 case 0x01:
7453 {
7454 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7455 return token_type::parse_error;
7456 }
7457 
7458 case 0x02:
7459 {
7460 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7461 return token_type::parse_error;
7462 }
7463 
7464 case 0x03:
7465 {
7466 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7467 return token_type::parse_error;
7468 }
7469 
7470 case 0x04:
7471 {
7472 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7473 return token_type::parse_error;
7474 }
7475 
7476 case 0x05:
7477 {
7478 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7479 return token_type::parse_error;
7480 }
7481 
7482 case 0x06:
7483 {
7484 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7485 return token_type::parse_error;
7486 }
7487 
7488 case 0x07:
7489 {
7490 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7491 return token_type::parse_error;
7492 }
7493 
7494 case 0x08:
7495 {
7496 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7497 return token_type::parse_error;
7498 }
7499 
7500 case 0x09:
7501 {
7502 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7503 return token_type::parse_error;
7504 }
7505 
7506 case 0x0A:
7507 {
7508 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7509 return token_type::parse_error;
7510 }
7511 
7512 case 0x0B:
7513 {
7514 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7515 return token_type::parse_error;
7516 }
7517 
7518 case 0x0C:
7519 {
7520 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7521 return token_type::parse_error;
7522 }
7523 
7524 case 0x0D:
7525 {
7526 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7527 return token_type::parse_error;
7528 }
7529 
7530 case 0x0E:
7531 {
7532 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7533 return token_type::parse_error;
7534 }
7535 
7536 case 0x0F:
7537 {
7538 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7539 return token_type::parse_error;
7540 }
7541 
7542 case 0x10:
7543 {
7544 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7545 return token_type::parse_error;
7546 }
7547 
7548 case 0x11:
7549 {
7550 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7551 return token_type::parse_error;
7552 }
7553 
7554 case 0x12:
7555 {
7556 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7557 return token_type::parse_error;
7558 }
7559 
7560 case 0x13:
7561 {
7562 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7563 return token_type::parse_error;
7564 }
7565 
7566 case 0x14:
7567 {
7568 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7569 return token_type::parse_error;
7570 }
7571 
7572 case 0x15:
7573 {
7574 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7575 return token_type::parse_error;
7576 }
7577 
7578 case 0x16:
7579 {
7580 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7581 return token_type::parse_error;
7582 }
7583 
7584 case 0x17:
7585 {
7586 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7587 return token_type::parse_error;
7588 }
7589 
7590 case 0x18:
7591 {
7592 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7593 return token_type::parse_error;
7594 }
7595 
7596 case 0x19:
7597 {
7598 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7599 return token_type::parse_error;
7600 }
7601 
7602 case 0x1A:
7603 {
7604 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7605 return token_type::parse_error;
7606 }
7607 
7608 case 0x1B:
7609 {
7610 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7611 return token_type::parse_error;
7612 }
7613 
7614 case 0x1C:
7615 {
7616 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7617 return token_type::parse_error;
7618 }
7619 
7620 case 0x1D:
7621 {
7622 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7623 return token_type::parse_error;
7624 }
7625 
7626 case 0x1E:
7627 {
7628 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7629 return token_type::parse_error;
7630 }
7631 
7632 case 0x1F:
7633 {
7634 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7635 return token_type::parse_error;
7636 }
7637 
7638 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7639 case 0x20:
7640 case 0x21:
7641 case 0x23:
7642 case 0x24:
7643 case 0x25:
7644 case 0x26:
7645 case 0x27:
7646 case 0x28:
7647 case 0x29:
7648 case 0x2A:
7649 case 0x2B:
7650 case 0x2C:
7651 case 0x2D:
7652 case 0x2E:
7653 case 0x2F:
7654 case 0x30:
7655 case 0x31:
7656 case 0x32:
7657 case 0x33:
7658 case 0x34:
7659 case 0x35:
7660 case 0x36:
7661 case 0x37:
7662 case 0x38:
7663 case 0x39:
7664 case 0x3A:
7665 case 0x3B:
7666 case 0x3C:
7667 case 0x3D:
7668 case 0x3E:
7669 case 0x3F:
7670 case 0x40:
7671 case 0x41:
7672 case 0x42:
7673 case 0x43:
7674 case 0x44:
7675 case 0x45:
7676 case 0x46:
7677 case 0x47:
7678 case 0x48:
7679 case 0x49:
7680 case 0x4A:
7681 case 0x4B:
7682 case 0x4C:
7683 case 0x4D:
7684 case 0x4E:
7685 case 0x4F:
7686 case 0x50:
7687 case 0x51:
7688 case 0x52:
7689 case 0x53:
7690 case 0x54:
7691 case 0x55:
7692 case 0x56:
7693 case 0x57:
7694 case 0x58:
7695 case 0x59:
7696 case 0x5A:
7697 case 0x5B:
7698 case 0x5D:
7699 case 0x5E:
7700 case 0x5F:
7701 case 0x60:
7702 case 0x61:
7703 case 0x62:
7704 case 0x63:
7705 case 0x64:
7706 case 0x65:
7707 case 0x66:
7708 case 0x67:
7709 case 0x68:
7710 case 0x69:
7711 case 0x6A:
7712 case 0x6B:
7713 case 0x6C:
7714 case 0x6D:
7715 case 0x6E:
7716 case 0x6F:
7717 case 0x70:
7718 case 0x71:
7719 case 0x72:
7720 case 0x73:
7721 case 0x74:
7722 case 0x75:
7723 case 0x76:
7724 case 0x77:
7725 case 0x78:
7726 case 0x79:
7727 case 0x7A:
7728 case 0x7B:
7729 case 0x7C:
7730 case 0x7D:
7731 case 0x7E:
7732 case 0x7F:
7733 {
7734 add(current);
7735 break;
7736 }
7737 
7738 // U+0080..U+07FF: bytes C2..DF 80..BF
7739 case 0xC2:
7740 case 0xC3:
7741 case 0xC4:
7742 case 0xC5:
7743 case 0xC6:
7744 case 0xC7:
7745 case 0xC8:
7746 case 0xC9:
7747 case 0xCA:
7748 case 0xCB:
7749 case 0xCC:
7750 case 0xCD:
7751 case 0xCE:
7752 case 0xCF:
7753 case 0xD0:
7754 case 0xD1:
7755 case 0xD2:
7756 case 0xD3:
7757 case 0xD4:
7758 case 0xD5:
7759 case 0xD6:
7760 case 0xD7:
7761 case 0xD8:
7762 case 0xD9:
7763 case 0xDA:
7764 case 0xDB:
7765 case 0xDC:
7766 case 0xDD:
7767 case 0xDE:
7768 case 0xDF:
7769 {
7770 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7771 {
7772 return token_type::parse_error;
7773 }
7774 break;
7775 }
7776 
7777 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7778 case 0xE0:
7779 {
7780 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7781 {
7782 return token_type::parse_error;
7783 }
7784 break;
7785 }
7786 
7787 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7788 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7789 case 0xE1:
7790 case 0xE2:
7791 case 0xE3:
7792 case 0xE4:
7793 case 0xE5:
7794 case 0xE6:
7795 case 0xE7:
7796 case 0xE8:
7797 case 0xE9:
7798 case 0xEA:
7799 case 0xEB:
7800 case 0xEC:
7801 case 0xEE:
7802 case 0xEF:
7803 {
7804 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7805 {
7806 return token_type::parse_error;
7807 }
7808 break;
7809 }
7810 
7811 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7812 case 0xED:
7813 {
7814 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7815 {
7816 return token_type::parse_error;
7817 }
7818 break;
7819 }
7820 
7821 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7822 case 0xF0:
7823 {
7824 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7825 {
7826 return token_type::parse_error;
7827 }
7828 break;
7829 }
7830 
7831 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7832 case 0xF1:
7833 case 0xF2:
7834 case 0xF3:
7835 {
7836 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7837 {
7838 return token_type::parse_error;
7839 }
7840 break;
7841 }
7842 
7843 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7844 case 0xF4:
7845 {
7846 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7847 {
7848 return token_type::parse_error;
7849 }
7850 break;
7851 }
7852 
7853 // remaining bytes (80..C1 and F5..FF) are ill-formed
7854 default:
7855 {
7856 error_message = "invalid string: ill-formed UTF-8 byte";
7857 return token_type::parse_error;
7858 }
7859 }
7860 }
7861 }
7862 
7863 /*!
7864 * @brief scan a comment
7865 * @return whether comment could be scanned successfully
7866 */
7867 bool scan_comment()
7868 {
7869 switch (get())
7870 {
7871 // single-line comments skip input until a newline or EOF is read
7872 case '/':
7873 {
7874 while (true)
7875 {
7876 switch (get())
7877 {
7878 case '\n':
7879 case '\r':
7880 case char_traits<char_type>::eof():
7881 case '\0':
7882 return true;
7883 
7884 default:
7885 break;
7886 }
7887 }
7888 }
7889 
7890 // multi-line comments skip input until */ is read
7891 case '*':
7892 {
7893 while (true)
7894 {
7895 switch (get())
7896 {
7897 case char_traits<char_type>::eof():
7898 case '\0':
7899 {
7900 error_message = "invalid comment; missing closing '*/'";
7901 return false;
7902 }
7903 
7904 case '*':
7905 {
7906 switch (get())
7907 {
7908 case '/':
7909 return true;
7910 
7911 default:
7912 {
7913 unget();
7914 continue;
7915 }
7916 }
7917 }
7918 
7919 default:
7920 continue;
7921 }
7922 }
7923 }
7924 
7925 // unexpected character after reading '/'
7926 default:
7927 {
7928 error_message = "invalid comment; expecting '/' or '*' after '/'";
7929 return false;
7930 }
7931 }
7932 }
7933 
7934 JSON_HEDLEY_NON_NULL(2)
7935 static void strtof(float& f, const char* str, char** endptr) noexcept
7936 {
7937 f = std::strtof(str, endptr);
7938 }
7939 
7940 JSON_HEDLEY_NON_NULL(2)
7941 static void strtof(double& f, const char* str, char** endptr) noexcept
7942 {
7943 f = std::strtod(str, endptr);
7944 }
7945 
7946 JSON_HEDLEY_NON_NULL(2)
7947 static void strtof(long double& f, const char* str, char** endptr) noexcept
7948 {
7949 f = std::strtold(str, endptr);
7950 }
7951 
7952 /*!
7953 @brief scan a number literal
7954 
7955 This function scans a string according to Sect. 6 of RFC 8259.
7956 
7957 The function is realized with a deterministic finite state machine derived
7958 from the grammar described in RFC 8259. Starting in state "init", the
7959 input is read and used to determined the next state. Only state "done"
7960 accepts the number. State "error" is a trap state to model errors. In the
7961 table below, "anything" means any character but the ones listed before.
7962 
7963 state | 0 | 1-9 | e E | + | - | . | anything
7964 ---------|----------|----------|----------|---------|---------|----------|-----------
7965 init | zero | any1 | [error] | [error] | minus | [error] | [error]
7966 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
7967 zero | done | done | exponent | done | done | decimal1 | done
7968 any1 | any1 | any1 | exponent | done | done | decimal1 | done
7969 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
7970 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
7971 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
7972 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
7973 any2 | any2 | any2 | done | done | done | done | done
7974 
7975 The state machine is realized with one label per state (prefixed with
7976 "scan_number_") and `goto` statements between them. The state machine
7977 contains cycles, but any cycle can be left when EOF is read. Therefore,
7978 the function is guaranteed to terminate.
7979 
7980 During scanning, the read bytes are stored in token_buffer. This string is
7981 then converted to a signed integer, an unsigned integer, or a
7982 floating-point number.
7983 
7984 @return token_type::value_unsigned, token_type::value_integer, or
7985 token_type::value_float if number could be successfully scanned,
7986 token_type::parse_error otherwise
7987 
7988 @note The scanner is independent of the current locale. Internally, the
7989 locale's decimal point is used instead of `.` to work with the
7990 locale-dependent converters.
7991 */
7992 token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
7993 {
7994 // reset token_buffer to store the number's bytes
7995 reset();
7996 
7997 // the type of the parsed number; initially set to unsigned; will be
7998 // changed if minus sign, decimal point or exponent is read
7999 token_type number_type = token_type::value_unsigned;
8000 
8001 // state (init): we just found out we need to scan a number
8002 switch (current)
8003 {
8004 case '-':
8005 {
8006 add(current);
8007 goto scan_number_minus;
8008 }
8009 
8010 case '0':
8011 {
8012 add(current);
8013 goto scan_number_zero;
8014 }
8015 
8016 case '1':
8017 case '2':
8018 case '3':
8019 case '4':
8020 case '5':
8021 case '6':
8022 case '7':
8023 case '8':
8024 case '9':
8025 {
8026 add(current);
8027 goto scan_number_any1;
8028 }
8029 
8030 // all other characters are rejected outside scan_number()
8031 default: // LCOV_EXCL_LINE
8032 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8033 }
8034 
8035scan_number_minus:
8036 // state: we just parsed a leading minus sign
8037 number_type = token_type::value_integer;
8038 switch (get())
8039 {
8040 case '0':
8041 {
8042 add(current);
8043 goto scan_number_zero;
8044 }
8045 
8046 case '1':
8047 case '2':
8048 case '3':
8049 case '4':
8050 case '5':
8051 case '6':
8052 case '7':
8053 case '8':
8054 case '9':
8055 {
8056 add(current);
8057 goto scan_number_any1;
8058 }
8059 
8060 default:
8061 {
8062 error_message = "invalid number; expected digit after '-'";
8063 return token_type::parse_error;
8064 }
8065 }
8066 
8067scan_number_zero:
8068 // state: we just parse a zero (maybe with a leading minus sign)
8069 switch (get())
8070 {
8071 case '.':
8072 {
8073 add(decimal_point_char);
8074 decimal_point_position = token_buffer.size() - 1;
8075 goto scan_number_decimal1;
8076 }
8077 
8078 case 'e':
8079 case 'E':
8080 {
8081 add(current);
8082 goto scan_number_exponent;
8083 }
8084 
8085 default:
8086 goto scan_number_done;
8087 }
8088 
8089scan_number_any1:
8090 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8091 switch (get())
8092 {
8093 case '0':
8094 case '1':
8095 case '2':
8096 case '3':
8097 case '4':
8098 case '5':
8099 case '6':
8100 case '7':
8101 case '8':
8102 case '9':
8103 {
8104 add(current);
8105 goto scan_number_any1;
8106 }
8107 
8108 case '.':
8109 {
8110 add(decimal_point_char);
8111 decimal_point_position = token_buffer.size() - 1;
8112 goto scan_number_decimal1;
8113 }
8114 
8115 case 'e':
8116 case 'E':
8117 {
8118 add(current);
8119 goto scan_number_exponent;
8120 }
8121 
8122 default:
8123 goto scan_number_done;
8124 }
8125 
8126scan_number_decimal1:
8127 // state: we just parsed a decimal point
8128 number_type = token_type::value_float;
8129 switch (get())
8130 {
8131 case '0':
8132 case '1':
8133 case '2':
8134 case '3':
8135 case '4':
8136 case '5':
8137 case '6':
8138 case '7':
8139 case '8':
8140 case '9':
8141 {
8142 add(current);
8143 goto scan_number_decimal2;
8144 }
8145 
8146 default:
8147 {
8148 error_message = "invalid number; expected digit after '.'";
8149 return token_type::parse_error;
8150 }
8151 }
8152 
8153scan_number_decimal2:
8154 // we just parsed at least one number after a decimal point
8155 switch (get())
8156 {
8157 case '0':
8158 case '1':
8159 case '2':
8160 case '3':
8161 case '4':
8162 case '5':
8163 case '6':
8164 case '7':
8165 case '8':
8166 case '9':
8167 {
8168 add(current);
8169 goto scan_number_decimal2;
8170 }
8171 
8172 case 'e':
8173 case 'E':
8174 {
8175 add(current);
8176 goto scan_number_exponent;
8177 }
8178 
8179 default:
8180 goto scan_number_done;
8181 }
8182 
8183scan_number_exponent:
8184 // we just parsed an exponent
8185 number_type = token_type::value_float;
8186 switch (get())
8187 {
8188 case '+':
8189 case '-':
8190 {
8191 add(current);
8192 goto scan_number_sign;
8193 }
8194 
8195 case '0':
8196 case '1':
8197 case '2':
8198 case '3':
8199 case '4':
8200 case '5':
8201 case '6':
8202 case '7':
8203 case '8':
8204 case '9':
8205 {
8206 add(current);
8207 goto scan_number_any2;
8208 }
8209 
8210 default:
8211 {
8212 error_message =
8213 "invalid number; expected '+', '-', or digit after exponent";
8214 return token_type::parse_error;
8215 }
8216 }
8217 
8218scan_number_sign:
8219 // we just parsed an exponent sign
8220 switch (get())
8221 {
8222 case '0':
8223 case '1':
8224 case '2':
8225 case '3':
8226 case '4':
8227 case '5':
8228 case '6':
8229 case '7':
8230 case '8':
8231 case '9':
8232 {
8233 add(current);
8234 goto scan_number_any2;
8235 }
8236 
8237 default:
8238 {
8239 error_message = "invalid number; expected digit after exponent sign";
8240 return token_type::parse_error;
8241 }
8242 }
8243 
8244scan_number_any2:
8245 // we just parsed a number after the exponent or exponent sign
8246 switch (get())
8247 {
8248 case '0':
8249 case '1':
8250 case '2':
8251 case '3':
8252 case '4':
8253 case '5':
8254 case '6':
8255 case '7':
8256 case '8':
8257 case '9':
8258 {
8259 add(current);
8260 goto scan_number_any2;
8261 }
8262 
8263 default:
8264 goto scan_number_done;
8265 }
8266 
8267scan_number_done:
8268 // unget the character after the number (we only read it to know that
8269 // we are done scanning a number)
8270 unget();
8271 
8272 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8273 errno = 0;
8274 
8275 // try to parse integers first and fall back to floats
8276 if (number_type == token_type::value_unsigned)
8277 {
8278 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8279 
8280 // we checked the number format before
8281 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8282 
8283 if (errno != ERANGE)
8284 {
8285 value_unsigned = static_cast<number_unsigned_t>(x);
8286 if (value_unsigned == x)
8287 {
8288 return token_type::value_unsigned;
8289 }
8290 }
8291 }
8292 else if (number_type == token_type::value_integer)
8293 {
8294 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8295 
8296 // we checked the number format before
8297 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8298 
8299 if (errno != ERANGE)
8300 {
8301 value_integer = static_cast<number_integer_t>(x);
8302 if (value_integer == x)
8303 {
8304 return token_type::value_integer;
8305 }
8306 }
8307 }
8308 
8309 // this code is reached if we parse a floating-point number or if an
8310 // integer conversion above failed
8311 strtof(value_float, token_buffer.data(), &endptr);
8312 
8313 // we checked the number format before
8314 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8315 
8316 return token_type::value_float;
8317 }
8318 
8319 /*!
8320 @param[in] literal_text the literal text to expect
8321 @param[in] length the length of the passed literal text
8322 @param[in] return_type the token type to return on success
8323 */
8324 JSON_HEDLEY_NON_NULL(2)
8325 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8326 token_type return_type)
8327 {
8328 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8329 for (std::size_t i = 1; i < length; ++i)
8330 {
8331 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8332 {
8333 error_message = "invalid literal";
8334 return token_type::parse_error;
8335 }
8336 }
8337 return return_type;
8338 }
8339 
8340 /////////////////////
8341 // input management
8342 /////////////////////
8343 
8344 /// reset token_buffer; current character is beginning of token
8345 void reset() noexcept
8346 {
8347 token_buffer.clear();
8348 token_string.clear();
8349 decimal_point_position = std::string::npos;
8350 token_string.push_back(char_traits<char_type>::to_char_type(current));
8351 }
8352 
8353 /*
8354 @brief get next character from the input
8355 
8356 This function provides the interface to the used input adapter. It does
8357 not throw in case the input reached EOF, but returns a
8358 `char_traits<char>::eof()` in that case. Stores the scanned characters
8359 for use in error messages.
8360 
8361 @return character read from the input
8362 */
8363 char_int_type get()
8364 {
8365 ++position.chars_read_total;
8366 ++position.chars_read_current_line;
8367 
8368 if (next_unget)
8369 {
8370 // just reset the next_unget variable and work with current
8371 next_unget = false;
8372 }
8373 else
8374 {
8375 current = ia.get_character();
8376 }
8377 
8378 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8379 {
8380 token_string.push_back(char_traits<char_type>::to_char_type(current));
8381 }
8382 
8383 if (current == '\n')
8384 {
8385 ++position.lines_read;
8386 position.chars_read_current_line = 0;
8387 }
8388 
8389 return current;
8390 }
8391 
8392 /*!
8393 @brief unget current character (read it again on next get)
8394 
8395 We implement unget by setting variable next_unget to true. The input is not
8396 changed - we just simulate ungetting by modifying chars_read_total,
8397 chars_read_current_line, and token_string. The next call to get() will
8398 behave as if the unget character is read again.
8399 */
8400 void unget()
8401 {
8402 next_unget = true;
8403 
8404 --position.chars_read_total;
8405 
8406 // in case we "unget" a newline, we have to also decrement the lines_read
8407 if (position.chars_read_current_line == 0)
8408 {
8409 if (position.lines_read > 0)
8410 {
8411 --position.lines_read;
8412 }
8413 }
8414 else
8415 {
8416 --position.chars_read_current_line;
8417 }
8418 
8419 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8420 {
8421 JSON_ASSERT(!token_string.empty());
8422 token_string.pop_back();
8423 }
8424 }
8425 
8426 /// add a character to token_buffer
8427 void add(char_int_type c)
8428 {
8429 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8430 }
8431 
8432 public:
8433 /////////////////////
8434 // value getters
8435 /////////////////////
8436 
8437 /// return integer value
8438 constexpr number_integer_t get_number_integer() const noexcept
8439 {
8440 return value_integer;
8441 }
8442 
8443 /// return unsigned integer value
8444 constexpr number_unsigned_t get_number_unsigned() const noexcept
8445 {
8446 return value_unsigned;
8447 }
8448 
8449 /// return floating-point value
8450 constexpr number_float_t get_number_float() const noexcept
8451 {
8452 return value_float;
8453 }
8454 
8455 /// return current string value (implicitly resets the token; useful only once)
8456 string_t& get_string()
8457 {
8458 // translate decimal points from locale back to '.' (#4084)
8459 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8460 {
8461 token_buffer[decimal_point_position] = '.';
8462 }
8463 return token_buffer;
8464 }
8465 
8466 /////////////////////
8467 // diagnostics
8468 /////////////////////
8469 
8470 /// return position of last read token
8471 constexpr position_t get_position() const noexcept
8472 {
8473 return position;
8474 }
8475 
8476 /// return the last read token (for errors only). Will never contain EOF
8477 /// (an arbitrary value that is not a valid char value, often -1), because
8478 /// 255 may legitimately occur. May contain NUL, which should be escaped.
8479 std::string get_token_string() const
8480 {
8481 // escape control characters
8482 std::string result;
8483 for (const auto c : token_string)
8484 {
8485 if (static_cast<unsigned char>(c) <= '\x1F')
8486 {
8487 // escape control characters
8488 std::array<char, 9> cs{{}};
8489 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8490 result += cs.data();
8491 }
8492 else
8493 {
8494 // add character as is
8495 result.push_back(static_cast<std::string::value_type>(c));
8496 }
8497 }
8498 
8499 return result;
8500 }
8501 
8502 /// return syntax error message
8503 JSON_HEDLEY_RETURNS_NON_NULL
8504 constexpr const char* get_error_message() const noexcept
8505 {
8506 return error_message;
8507 }
8508 
8509 /////////////////////
8510 // actual scanner
8511 /////////////////////
8512 
8513 /*!
8514 @brief skip the UTF-8 byte order mark
8515 @return true iff there is no BOM or the correct BOM has been skipped
8516 */
8517 bool skip_bom()
8518 {
8519 if (get() == 0xEF)
8520 {
8521 // check if we completely parse the BOM
8522 return get() == 0xBB && get() == 0xBF;
8523 }
8524 
8525 // the first character is not the beginning of the BOM; unget it to
8526 // process is later
8527 unget();
8528 return true;
8529 }
8530 
8531 void skip_whitespace()
8532 {
8533 do
8534 {
8535 get();
8536 }
8537 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8538 }
8539 
8540 token_type scan()
8541 {
8542 // initially, skip the BOM
8543 if (position.chars_read_total == 0 && !skip_bom())
8544 {
8545 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8546 return token_type::parse_error;
8547 }
8548 
8549 // read next character and ignore whitespace
8550 skip_whitespace();
8551 
8552 // ignore comments
8553 while (ignore_comments && current == '/')
8554 {
8555 if (!scan_comment())
8556 {
8557 return token_type::parse_error;
8558 }
8559 
8560 // skip following whitespace
8561 skip_whitespace();
8562 }
8563 
8564 switch (current)
8565 {
8566 // structural characters
8567 case '[':
8568 return token_type::begin_array;
8569 case ']':
8570 return token_type::end_array;
8571 case '{':
8572 return token_type::begin_object;
8573 case '}':
8574 return token_type::end_object;
8575 case ':':
8576 return token_type::name_separator;
8577 case ',':
8578 return token_type::value_separator;
8579 
8580 // literals
8581 case 't':
8582 {
8583 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')}};
8584 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8585 }
8586 case 'f':
8587 {
8588 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')}};
8589 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8590 }
8591 case 'n':
8592 {
8593 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')}};
8594 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8595 }
8596 
8597 // string
8598 case '\"':
8599 return scan_string();
8600 
8601 // number
8602 case '-':
8603 case '0':
8604 case '1':
8605 case '2':
8606 case '3':
8607 case '4':
8608 case '5':
8609 case '6':
8610 case '7':
8611 case '8':
8612 case '9':
8613 return scan_number();
8614 
8615 // end of input (the null byte is needed when parsing from
8616 // string literals)
8617 case '\0':
8618 case char_traits<char_type>::eof():
8619 return token_type::end_of_input;
8620 
8621 // error
8622 default:
8623 error_message = "invalid literal";
8624 return token_type::parse_error;
8625 }
8626 }
8627 
8628 private:
8629 /// input adapter
8630 InputAdapterType ia;
8631 
8632 /// whether comments should be ignored (true) or signaled as errors (false)
8633 const bool ignore_comments = false;
8634 
8635 /// the current character
8636 char_int_type current = char_traits<char_type>::eof();
8637 
8638 /// whether the next get() call should just return current
8639 bool next_unget = false;
8640 
8641 /// the start position of the current token
8642 position_t position {};
8643 
8644 /// raw input token string (for error messages)
8645 std::vector<char_type> token_string {};
8646 
8647 /// buffer for variable-length tokens (numbers, strings)
8648 string_t token_buffer {};
8649 
8650 /// a description of occurred lexer errors
8651 const char* error_message = "";
8652 
8653 // number values
8654 number_integer_t value_integer = 0;
8655 number_unsigned_t value_unsigned = 0;
8656 number_float_t value_float = 0;
8657 
8658 /// the decimal point
8659 const char_int_type decimal_point_char = '.';
8660 /// the position of the decimal point in the input
8661 std::size_t decimal_point_position = std::string::npos;
8662};
8663 
8664} // namespace detail
8665NLOHMANN_JSON_NAMESPACE_END
8666 
8667// #include <nlohmann/detail/macro_scope.hpp>
8668 
8669// #include <nlohmann/detail/string_concat.hpp>
8670 
8671NLOHMANN_JSON_NAMESPACE_BEGIN
8672 
8673/*!
8674@brief SAX interface
8675 
8676This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
8677Each function is called in different situations while the input is parsed. The
8678boolean return value informs the parser whether to continue processing the
8679input.
8680*/
8681template<typename BasicJsonType>
8682struct json_sax
8683{
8684 using number_integer_t = typename BasicJsonType::number_integer_t;
8685 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8686 using number_float_t = typename BasicJsonType::number_float_t;
8687 using string_t = typename BasicJsonType::string_t;
8688 using binary_t = typename BasicJsonType::binary_t;
8689 
8690 /*!
8691 @brief a null value was read
8692 @return whether parsing should proceed
8693 */
8694 virtual bool null() = 0;
8695 
8696 /*!
8697 @brief a boolean value was read
8698 @param[in] val boolean value
8699 @return whether parsing should proceed
8700 */
8701 virtual bool boolean(bool val) = 0;
8702 
8703 /*!
8704 @brief an integer number was read
8705 @param[in] val integer value
8706 @return whether parsing should proceed
8707 */
8708 virtual bool number_integer(number_integer_t val) = 0;
8709 
8710 /*!
8711 @brief an unsigned integer number was read
8712 @param[in] val unsigned integer value
8713 @return whether parsing should proceed
8714 */
8715 virtual bool number_unsigned(number_unsigned_t val) = 0;
8716 
8717 /*!
8718 @brief a floating-point number was read
8719 @param[in] val floating-point value
8720 @param[in] s raw token value
8721 @return whether parsing should proceed
8722 */
8723 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8724 
8725 /*!
8726 @brief a string value was read
8727 @param[in] val string value
8728 @return whether parsing should proceed
8729 @note It is safe to move the passed string value.
8730 */
8731 virtual bool string(string_t& val) = 0;
8732 
8733 /*!
8734 @brief a binary value was read
8735 @param[in] val binary value
8736 @return whether parsing should proceed
8737 @note It is safe to move the passed binary value.
8738 */
8739 virtual bool binary(binary_t& val) = 0;
8740 
8741 /*!
8742 @brief the beginning of an object was read
8743 @param[in] elements number of object elements or -1 if unknown
8744 @return whether parsing should proceed
8745 @note binary formats may report the number of elements
8746 */
8747 virtual bool start_object(std::size_t elements) = 0;
8748 
8749 /*!
8750 @brief an object key was read
8751 @param[in] val object key
8752 @return whether parsing should proceed
8753 @note It is safe to move the passed string.
8754 */
8755 virtual bool key(string_t& val) = 0;
8756 
8757 /*!
8758 @brief the end of an object was read
8759 @return whether parsing should proceed
8760 */
8761 virtual bool end_object() = 0;
8762 
8763 /*!
8764 @brief the beginning of an array was read
8765 @param[in] elements number of array elements or -1 if unknown
8766 @return whether parsing should proceed
8767 @note binary formats may report the number of elements
8768 */
8769 virtual bool start_array(std::size_t elements) = 0;
8770 
8771 /*!
8772 @brief the end of an array was read
8773 @return whether parsing should proceed
8774 */
8775 virtual bool end_array() = 0;
8776 
8777 /*!
8778 @brief a parse error occurred
8779 @param[in] position the position in the input where the error occurs
8780 @param[in] last_token the last read token
8781 @param[in] ex an exception object describing the error
8782 @return whether parsing should proceed (must return false)
8783 */
8784 virtual bool parse_error(std::size_t position,
8785 const std::string& last_token,
8786 const detail::exception& ex) = 0;
8787 
8788 json_sax() = default;
8789 json_sax(const json_sax&) = default;
8790 json_sax(json_sax&&) noexcept = default;
8791 json_sax& operator=(const json_sax&) = default;
8792 json_sax& operator=(json_sax&&) noexcept = default;
8793 virtual ~json_sax() = default;
8794};
8795 
8796namespace detail
8797{
8798constexpr std::size_t unknown_size()
8799{
8800 return (std::numeric_limits<std::size_t>::max)();
8801}
8802 
8803/*!
8804@brief SAX implementation to create a JSON value from SAX events
8805 
8806This class implements the @ref json_sax interface and processes the SAX events
8807to create a JSON value which makes it basically a DOM parser. The structure or
8808hierarchy of the JSON value is managed by the stack `ref_stack` which contains
8809a pointer to the respective array or object for each recursion depth.
8810 
8811After successful parsing, the value that is passed by reference to the
8812constructor contains the parsed value.
8813 
8814@tparam BasicJsonType the JSON type
8815*/
8816template<typename BasicJsonType, typename InputAdapterType>
8817class json_sax_dom_parser
8818{
8819 public:
8820 using number_integer_t = typename BasicJsonType::number_integer_t;
8821 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8822 using number_float_t = typename BasicJsonType::number_float_t;
8823 using string_t = typename BasicJsonType::string_t;
8824 using binary_t = typename BasicJsonType::binary_t;
8825 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
8826 
8827 /*!
8828 @param[in,out] r reference to a JSON value that is manipulated while
8829 parsing
8830 @param[in] allow_exceptions_ whether parse errors yield exceptions
8831 */
8832 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8833 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8834 {}
8835 
8836 // make class move-only
8837 json_sax_dom_parser(const json_sax_dom_parser&) = delete;
8838 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8839 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
8840 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8841 ~json_sax_dom_parser() = default;
8842 
8843 bool null()
8844 {
8845 handle_value(nullptr);
8846 return true;
8847 }
8848 
8849 bool boolean(bool val)
8850 {
8851 handle_value(val);
8852 return true;
8853 }
8854 
8855 bool number_integer(number_integer_t val)
8856 {
8857 handle_value(val);
8858 return true;
8859 }
8860 
8861 bool number_unsigned(number_unsigned_t val)
8862 {
8863 handle_value(val);
8864 return true;
8865 }
8866 
8867 bool number_float(number_float_t val, const string_t& /*unused*/)
8868 {
8869 handle_value(val);
8870 return true;
8871 }
8872 
8873 bool string(string_t& val)
8874 {
8875 handle_value(val);
8876 return true;
8877 }
8878 
8879 bool binary(binary_t& val)
8880 {
8881 handle_value(std::move(val));
8882 return true;
8883 }
8884 
8885 bool start_object(std::size_t len)
8886 {
8887 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8888 
8889#if JSON_DIAGNOSTIC_POSITIONS
8890 // Manually set the start position of the object here.
8891 // Ensure this is after the call to handle_value to ensure correct start position.
8892 if (m_lexer_ref)
8893 {
8894 // Lexer has read the first character of the object, so
8895 // subtract 1 from the position to get the correct start position.
8896 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8897 }
8898#endif
8899 
8900 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8901 {
8902 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8903 }
8904 
8905 return true;
8906 }
8907 
8908 bool key(string_t& val)
8909 {
8910 JSON_ASSERT(!ref_stack.empty());
8911 JSON_ASSERT(ref_stack.back()->is_object());
8912 
8913 // add null at given key and store the reference for later
8914 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8915 return true;
8916 }
8917 
8918 bool end_object()
8919 {
8920 JSON_ASSERT(!ref_stack.empty());
8921 JSON_ASSERT(ref_stack.back()->is_object());
8922 
8923#if JSON_DIAGNOSTIC_POSITIONS
8924 if (m_lexer_ref)
8925 {
8926 // Lexer's position is past the closing brace, so set that as the end position.
8927 ref_stack.back()->end_position = m_lexer_ref->get_position();
8928 }
8929#endif
8930 
8931 ref_stack.back()->set_parents();
8932 ref_stack.pop_back();
8933 return true;
8934 }
8935 
8936 bool start_array(std::size_t len)
8937 {
8938 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8939 
8940#if JSON_DIAGNOSTIC_POSITIONS
8941 // Manually set the start position of the array here.
8942 // Ensure this is after the call to handle_value to ensure correct start position.
8943 if (m_lexer_ref)
8944 {
8945 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8946 }
8947#endif
8948 
8949 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8950 {
8951 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8952 }
8953 
8954 return true;
8955 }
8956 
8957 bool end_array()
8958 {
8959 JSON_ASSERT(!ref_stack.empty());
8960 JSON_ASSERT(ref_stack.back()->is_array());
8961 
8962#if JSON_DIAGNOSTIC_POSITIONS
8963 if (m_lexer_ref)
8964 {
8965 // Lexer's position is past the closing bracket, so set that as the end position.
8966 ref_stack.back()->end_position = m_lexer_ref->get_position();
8967 }
8968#endif
8969 
8970 ref_stack.back()->set_parents();
8971 ref_stack.pop_back();
8972 return true;
8973 }
8974 
8975 template<class Exception>
8976 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
8977 const Exception& ex)
8978 {
8979 errored = true;
8980 static_cast<void>(ex);
8981 if (allow_exceptions)
8982 {
8983 JSON_THROW(ex);
8984 }
8985 return false;
8986 }
8987 
8988 constexpr bool is_errored() const
8989 {
8990 return errored;
8991 }
8992 
8993 private:
8994 
8995#if JSON_DIAGNOSTIC_POSITIONS
8996 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
8997 {
8998 if (m_lexer_ref)
8999 {
9000 // Lexer has read past the current field value, so set the end position to the current position.
9001 // The start position will be set below based on the length of the string representation
9002 // of the value.
9003 v.end_position = m_lexer_ref->get_position();
9004 
9005 switch (v.type())
9006 {
9007 case value_t::boolean:
9008 {
9009 // 4 and 5 are the string length of "true" and "false"
9010 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9011 break;
9012 }
9013 
9014 case value_t::null:
9015 {
9016 // 4 is the string length of "null"
9017 v.start_position = v.end_position - 4;
9018 break;
9019 }
9020 
9021 case value_t::string:
9022 {
9023 // include the length of the quotes, which is 2
9024 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9025 break;
9026 }
9027 
9028 // As we handle the start and end positions for values created during parsing,
9029 // we do not expect the following value type to be called. Regardless, set the positions
9030 // in case this is created manually or through a different constructor. Exclude from lcov
9031 // since the exact condition of this switch is esoteric.
9032 // LCOV_EXCL_START
9033 case value_t::discarded:
9034 {
9035 v.end_position = std::string::npos;
9036 v.start_position = v.end_position;
9037 break;
9038 }
9039 // LCOV_EXCL_STOP
9040 case value_t::binary:
9041 case value_t::number_integer:
9042 case value_t::number_unsigned:
9043 case value_t::number_float:
9044 {
9045 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9046 break;
9047 }
9048 case value_t::object:
9049 case value_t::array:
9050 {
9051 // object and array are handled in start_object() and start_array() handlers
9052 // skip setting the values here.
9053 break;
9054 }
9055 default: // LCOV_EXCL_LINE
9056 // Handle all possible types discretely, default handler should never be reached.
9057 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9058 }
9059 }
9060 }
9061#endif
9062 
9063 /*!
9064 @invariant If the ref stack is empty, then the passed value will be the new
9065 root.
9066 @invariant If the ref stack contains a value, then it is an array or an
9067 object to which we can add elements
9068 */
9069 template<typename Value>
9070 JSON_HEDLEY_RETURNS_NON_NULL
9071 BasicJsonType* handle_value(Value&& v)
9072 {
9073 if (ref_stack.empty())
9074 {
9075 root = BasicJsonType(std::forward<Value>(v));
9076 
9077#if JSON_DIAGNOSTIC_POSITIONS
9078 handle_diagnostic_positions_for_json_value(root);
9079#endif
9080 
9081 return &root;
9082 }
9083 
9084 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9085 
9086 if (ref_stack.back()->is_array())
9087 {
9088 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9089 
9090#if JSON_DIAGNOSTIC_POSITIONS
9091 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9092#endif
9093 
9094 return &(ref_stack.back()->m_data.m_value.array->back());
9095 }
9096 
9097 JSON_ASSERT(ref_stack.back()->is_object());
9098 JSON_ASSERT(object_element);
9099 *object_element = BasicJsonType(std::forward<Value>(v));
9100 
9101#if JSON_DIAGNOSTIC_POSITIONS
9102 handle_diagnostic_positions_for_json_value(*object_element);
9103#endif
9104 
9105 return object_element;
9106 }
9107 
9108 /// the parsed JSON value
9109 BasicJsonType& root;
9110 /// stack to model hierarchy of values
9111 std::vector<BasicJsonType*> ref_stack {};
9112 /// helper to hold the reference for the next object element
9113 BasicJsonType* object_element = nullptr;
9114 /// whether a syntax error occurred
9115 bool errored = false;
9116 /// whether to throw exceptions in case of errors
9117 const bool allow_exceptions = true;
9118 /// the lexer reference to obtain the current position
9119 lexer_t* m_lexer_ref = nullptr;
9120};
9121 
9122template<typename BasicJsonType, typename InputAdapterType>
9123class json_sax_dom_callback_parser
9124{
9125 public:
9126 using number_integer_t = typename BasicJsonType::number_integer_t;
9127 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9128 using number_float_t = typename BasicJsonType::number_float_t;
9129 using string_t = typename BasicJsonType::string_t;
9130 using binary_t = typename BasicJsonType::binary_t;
9131 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9132 using parse_event_t = typename BasicJsonType::parse_event_t;
9133 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
9134 
9135 json_sax_dom_callback_parser(BasicJsonType& r,
9136 parser_callback_t cb,
9137 const bool allow_exceptions_ = true,
9138 lexer_t* lexer_ = nullptr)
9139 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9140 {
9141 keep_stack.push_back(true);
9142 }
9143 
9144 // make class move-only
9145 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
9146 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9147 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
9148 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9149 ~json_sax_dom_callback_parser() = default;
9150 
9151 bool null()
9152 {
9153 handle_value(nullptr);
9154 return true;
9155 }
9156 
9157 bool boolean(bool val)
9158 {
9159 handle_value(val);
9160 return true;
9161 }
9162 
9163 bool number_integer(number_integer_t val)
9164 {
9165 handle_value(val);
9166 return true;
9167 }
9168 
9169 bool number_unsigned(number_unsigned_t val)
9170 {
9171 handle_value(val);
9172 return true;
9173 }
9174 
9175 bool number_float(number_float_t val, const string_t& /*unused*/)
9176 {
9177 handle_value(val);
9178 return true;
9179 }
9180 
9181 bool string(string_t& val)
9182 {
9183 handle_value(val);
9184 return true;
9185 }
9186 
9187 bool binary(binary_t& val)
9188 {
9189 handle_value(std::move(val));
9190 return true;
9191 }
9192 
9193 bool start_object(std::size_t len)
9194 {
9195 // check callback for object start
9196 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9197 keep_stack.push_back(keep);
9198 
9199 auto val = handle_value(BasicJsonType::value_t::object, true);
9200 ref_stack.push_back(val.second);
9201 
9202 if (ref_stack.back())
9203 {
9204 
9205#if JSON_DIAGNOSTIC_POSITIONS
9206 // Manually set the start position of the object here.
9207 // Ensure this is after the call to handle_value to ensure correct start position.
9208 if (m_lexer_ref)
9209 {
9210 // Lexer has read the first character of the object, so
9211 // subtract 1 from the position to get the correct start position.
9212 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9213 }
9214#endif
9215 
9216 // check object limit
9217 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9218 {
9219 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9220 }
9221 }
9222 return true;
9223 }
9224 
9225 bool key(string_t& val)
9226 {
9227 BasicJsonType k = BasicJsonType(val);
9228 
9229 // check callback for key
9230 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9231 key_keep_stack.push_back(keep);
9232 
9233 // add discarded value at given key and store the reference for later
9234 if (keep && ref_stack.back())
9235 {
9236 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9237 }
9238 
9239 return true;
9240 }
9241 
9242 bool end_object()
9243 {
9244 if (ref_stack.back())
9245 {
9246 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9247 {
9248 // discard object
9249 *ref_stack.back() = discarded;
9250 
9251#if JSON_DIAGNOSTIC_POSITIONS
9252 // Set start/end positions for discarded object.
9253 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9254#endif
9255 }
9256 else
9257 {
9258 
9259#if JSON_DIAGNOSTIC_POSITIONS
9260 if (m_lexer_ref)
9261 {
9262 // Lexer's position is past the closing brace, so set that as the end position.
9263 ref_stack.back()->end_position = m_lexer_ref->get_position();
9264 }
9265#endif
9266 
9267 ref_stack.back()->set_parents();
9268 }
9269 }
9270 
9271 JSON_ASSERT(!ref_stack.empty());
9272 JSON_ASSERT(!keep_stack.empty());
9273 ref_stack.pop_back();
9274 keep_stack.pop_back();
9275 
9276 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9277 {
9278 // remove discarded value
9279 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9280 {
9281 if (it->is_discarded())
9282 {
9283 ref_stack.back()->erase(it);
9284 break;
9285 }
9286 }
9287 }
9288 
9289 return true;
9290 }
9291 
9292 bool start_array(std::size_t len)
9293 {
9294 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9295 keep_stack.push_back(keep);
9296 
9297 auto val = handle_value(BasicJsonType::value_t::array, true);
9298 ref_stack.push_back(val.second);
9299 
9300 if (ref_stack.back())
9301 {
9302 
9303#if JSON_DIAGNOSTIC_POSITIONS
9304 // Manually set the start position of the array here.
9305 // Ensure this is after the call to handle_value to ensure correct start position.
9306 if (m_lexer_ref)
9307 {
9308 // Lexer has read the first character of the array, so
9309 // subtract 1 from the position to get the correct start position.
9310 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9311 }
9312#endif
9313 
9314 // check array limit
9315 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9316 {
9317 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9318 }
9319 }
9320 
9321 return true;
9322 }
9323 
9324 bool end_array()
9325 {
9326 bool keep = true;
9327 
9328 if (ref_stack.back())
9329 {
9330 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9331 if (keep)
9332 {
9333 
9334#if JSON_DIAGNOSTIC_POSITIONS
9335 if (m_lexer_ref)
9336 {
9337 // Lexer's position is past the closing bracket, so set that as the end position.
9338 ref_stack.back()->end_position = m_lexer_ref->get_position();
9339 }
9340#endif
9341 
9342 ref_stack.back()->set_parents();
9343 }
9344 else
9345 {
9346 // discard array
9347 *ref_stack.back() = discarded;
9348 
9349#if JSON_DIAGNOSTIC_POSITIONS
9350 // Set start/end positions for discarded array.
9351 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9352#endif
9353 }
9354 }
9355 
9356 JSON_ASSERT(!ref_stack.empty());
9357 JSON_ASSERT(!keep_stack.empty());
9358 ref_stack.pop_back();
9359 keep_stack.pop_back();
9360 
9361 // remove discarded value
9362 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9363 {
9364 ref_stack.back()->m_data.m_value.array->pop_back();
9365 }
9366 
9367 return true;
9368 }
9369 
9370 template<class Exception>
9371 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9372 const Exception& ex)
9373 {
9374 errored = true;
9375 static_cast<void>(ex);
9376 if (allow_exceptions)
9377 {
9378 JSON_THROW(ex);
9379 }
9380 return false;
9381 }
9382 
9383 constexpr bool is_errored() const
9384 {
9385 return errored;
9386 }
9387 
9388 private:
9389 
9390#if JSON_DIAGNOSTIC_POSITIONS
9391 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9392 {
9393 if (m_lexer_ref)
9394 {
9395 // Lexer has read past the current field value, so set the end position to the current position.
9396 // The start position will be set below based on the length of the string representation
9397 // of the value.
9398 v.end_position = m_lexer_ref->get_position();
9399 
9400 switch (v.type())
9401 {
9402 case value_t::boolean:
9403 {
9404 // 4 and 5 are the string length of "true" and "false"
9405 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9406 break;
9407 }
9408 
9409 case value_t::null:
9410 {
9411 // 4 is the string length of "null"
9412 v.start_position = v.end_position - 4;
9413 break;
9414 }
9415 
9416 case value_t::string:
9417 {
9418 // include the length of the quotes, which is 2
9419 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9420 break;
9421 }
9422 
9423 case value_t::discarded:
9424 {
9425 v.end_position = std::string::npos;
9426 v.start_position = v.end_position;
9427 break;
9428 }
9429 
9430 case value_t::binary:
9431 case value_t::number_integer:
9432 case value_t::number_unsigned:
9433 case value_t::number_float:
9434 {
9435 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9436 break;
9437 }
9438 
9439 case value_t::object:
9440 case value_t::array:
9441 {
9442 // object and array are handled in start_object() and start_array() handlers
9443 // skip setting the values here.
9444 break;
9445 }
9446 default: // LCOV_EXCL_LINE
9447 // Handle all possible types discretely, default handler should never be reached.
9448 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9449 }
9450 }
9451 }
9452#endif
9453 
9454 /*!
9455 @param[in] v value to add to the JSON value we build during parsing
9456 @param[in] skip_callback whether we should skip calling the callback
9457 function; this is required after start_array() and
9458 start_object() SAX events, because otherwise we would call the
9459 callback function with an empty array or object, respectively.
9460 
9461 @invariant If the ref stack is empty, then the passed value will be the new
9462 root.
9463 @invariant If the ref stack contains a value, then it is an array or an
9464 object to which we can add elements
9465 
9466 @return pair of boolean (whether value should be kept) and pointer (to the
9467 passed value in the ref_stack hierarchy; nullptr if not kept)
9468 */
9469 template<typename Value>
9470 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9471 {
9472 JSON_ASSERT(!keep_stack.empty());
9473 
9474 // do not handle this value if we know it would be added to a discarded
9475 // container
9476 if (!keep_stack.back())
9477 {
9478 return {false, nullptr};
9479 }
9480 
9481 // create value
9482 auto value = BasicJsonType(std::forward<Value>(v));
9483 
9484#if JSON_DIAGNOSTIC_POSITIONS
9485 handle_diagnostic_positions_for_json_value(value);
9486#endif
9487 
9488 // check callback
9489 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9490 
9491 // do not handle this value if we just learnt it shall be discarded
9492 if (!keep)
9493 {
9494 return {false, nullptr};
9495 }
9496 
9497 if (ref_stack.empty())
9498 {
9499 root = std::move(value);
9500 return {true, & root};
9501 }
9502 
9503 // skip this value if we already decided to skip the parent
9504 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9505 if (!ref_stack.back())
9506 {
9507 return {false, nullptr};
9508 }
9509 
9510 // we now only expect arrays and objects
9511 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9512 
9513 // array
9514 if (ref_stack.back()->is_array())
9515 {
9516 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9517 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9518 }
9519 
9520 // object
9521 JSON_ASSERT(ref_stack.back()->is_object());
9522 // check if we should store an element for the current key
9523 JSON_ASSERT(!key_keep_stack.empty());
9524 const bool store_element = key_keep_stack.back();
9525 key_keep_stack.pop_back();
9526 
9527 if (!store_element)
9528 {
9529 return {false, nullptr};
9530 }
9531 
9532 JSON_ASSERT(object_element);
9533 *object_element = std::move(value);
9534 return {true, object_element};
9535 }
9536 
9537 /// the parsed JSON value
9538 BasicJsonType& root;
9539 /// stack to model hierarchy of values
9540 std::vector<BasicJsonType*> ref_stack {};
9541 /// stack to manage which values to keep
9542 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9543 /// stack to manage which object keys to keep
9544 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9545 /// helper to hold the reference for the next object element
9546 BasicJsonType* object_element = nullptr;
9547 /// whether a syntax error occurred
9548 bool errored = false;
9549 /// callback function
9550 const parser_callback_t callback = nullptr;
9551 /// whether to throw exceptions in case of errors
9552 const bool allow_exceptions = true;
9553 /// a discarded value for the callback
9554 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9555 /// the lexer reference to obtain the current position
9556 lexer_t* m_lexer_ref = nullptr;
9557};
9558 
9559template<typename BasicJsonType>
9560class json_sax_acceptor
9561{
9562 public:
9563 using number_integer_t = typename BasicJsonType::number_integer_t;
9564 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9565 using number_float_t = typename BasicJsonType::number_float_t;
9566 using string_t = typename BasicJsonType::string_t;
9567 using binary_t = typename BasicJsonType::binary_t;
9568 
9569 bool null()
9570 {
9571 return true;
9572 }
9573 
9574 bool boolean(bool /*unused*/)
9575 {
9576 return true;
9577 }
9578 
9579 bool number_integer(number_integer_t /*unused*/)
9580 {
9581 return true;
9582 }
9583 
9584 bool number_unsigned(number_unsigned_t /*unused*/)
9585 {
9586 return true;
9587 }
9588 
9589 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9590 {
9591 return true;
9592 }
9593 
9594 bool string(string_t& /*unused*/)
9595 {
9596 return true;
9597 }
9598 
9599 bool binary(binary_t& /*unused*/)
9600 {
9601 return true;
9602 }
9603 
9604 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9605 {
9606 return true;
9607 }
9608 
9609 bool key(string_t& /*unused*/)
9610 {
9611 return true;
9612 }
9613 
9614 bool end_object()
9615 {
9616 return true;
9617 }
9618 
9619 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9620 {
9621 return true;
9622 }
9623 
9624 bool end_array()
9625 {
9626 return true;
9627 }
9628 
9629 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9630 {
9631 return false;
9632 }
9633};
9634 
9635} // namespace detail
9636NLOHMANN_JSON_NAMESPACE_END
9637 
9638// #include <nlohmann/detail/input/lexer.hpp>
9639 
9640// #include <nlohmann/detail/macro_scope.hpp>
9641 
9642// #include <nlohmann/detail/meta/is_sax.hpp>
9643// __ _____ _____ _____
9644// __| | __| | | | JSON for Modern C++
9645// | | |__ | | | | | | version 3.12.0
9646// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9647//
9648// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9649// SPDX-License-Identifier: MIT
9650 
9651 
9652 
9653#include <cstdint> // size_t
9654#include <utility> // declval
9655#include <string> // string
9656 
9657// #include <nlohmann/detail/abi_macros.hpp>
9658 
9659// #include <nlohmann/detail/meta/detected.hpp>
9660 
9661// #include <nlohmann/detail/meta/type_traits.hpp>
9662 
9663 
9664NLOHMANN_JSON_NAMESPACE_BEGIN
9665namespace detail
9666{
9667 
9668template<typename T>
9669using null_function_t = decltype(std::declval<T&>().null());
9670 
9671template<typename T>
9672using boolean_function_t =
9673 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9674 
9675template<typename T, typename Integer>
9676using number_integer_function_t =
9677 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9678 
9679template<typename T, typename Unsigned>
9680using number_unsigned_function_t =
9681 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9682 
9683template<typename T, typename Float, typename String>
9684using number_float_function_t = decltype(std::declval<T&>().number_float(
9685 std::declval<Float>(), std::declval<const String&>()));
9686 
9687template<typename T, typename String>
9688using string_function_t =
9689 decltype(std::declval<T&>().string(std::declval<String&>()));
9690 
9691template<typename T, typename Binary>
9692using binary_function_t =
9693 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9694 
9695template<typename T>
9696using start_object_function_t =
9697 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9698 
9699template<typename T, typename String>
9700using key_function_t =
9701 decltype(std::declval<T&>().key(std::declval<String&>()));
9702 
9703template<typename T>
9704using end_object_function_t = decltype(std::declval<T&>().end_object());
9705 
9706template<typename T>
9707using start_array_function_t =
9708 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9709 
9710template<typename T>
9711using end_array_function_t = decltype(std::declval<T&>().end_array());
9712 
9713template<typename T, typename Exception>
9714using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9715 std::declval<std::size_t>(), std::declval<const std::string&>(),
9716 std::declval<const Exception&>()));
9717 
9718template<typename SAX, typename BasicJsonType>
9719struct is_sax
9720{
9721 private:
9722 static_assert(is_basic_json<BasicJsonType>::value,
9723 "BasicJsonType must be of type basic_json<...>");
9724 
9725 using number_integer_t = typename BasicJsonType::number_integer_t;
9726 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9727 using number_float_t = typename BasicJsonType::number_float_t;
9728 using string_t = typename BasicJsonType::string_t;
9729 using binary_t = typename BasicJsonType::binary_t;
9730 using exception_t = typename BasicJsonType::exception;
9731 
9732 public:
9733 static constexpr bool value =
9734 is_detected_exact<bool, null_function_t, SAX>::value &&
9735 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9736 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9737 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9738 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9739 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9740 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9741 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9742 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9743 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9744 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9745 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9746 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9747};
9748 
9749template<typename SAX, typename BasicJsonType>
9750struct is_sax_static_asserts
9751{
9752 private:
9753 static_assert(is_basic_json<BasicJsonType>::value,
9754 "BasicJsonType must be of type basic_json<...>");
9755 
9756 using number_integer_t = typename BasicJsonType::number_integer_t;
9757 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9758 using number_float_t = typename BasicJsonType::number_float_t;
9759 using string_t = typename BasicJsonType::string_t;
9760 using binary_t = typename BasicJsonType::binary_t;
9761 using exception_t = typename BasicJsonType::exception;
9762 
9763 public:
9764 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9765 "Missing/invalid function: bool null()");
9766 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9767 "Missing/invalid function: bool boolean(bool)");
9768 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9769 "Missing/invalid function: bool boolean(bool)");
9770 static_assert(
9771 is_detected_exact<bool, number_integer_function_t, SAX,
9772 number_integer_t>::value,
9773 "Missing/invalid function: bool number_integer(number_integer_t)");
9774 static_assert(
9775 is_detected_exact<bool, number_unsigned_function_t, SAX,
9776 number_unsigned_t>::value,
9777 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9778 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9779 number_float_t, string_t>::value,
9780 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9781 static_assert(
9782 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9783 "Missing/invalid function: bool string(string_t&)");
9784 static_assert(
9785 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9786 "Missing/invalid function: bool binary(binary_t&)");
9787 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9788 "Missing/invalid function: bool start_object(std::size_t)");
9789 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9790 "Missing/invalid function: bool key(string_t&)");
9791 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9792 "Missing/invalid function: bool end_object()");
9793 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9794 "Missing/invalid function: bool start_array(std::size_t)");
9795 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9796 "Missing/invalid function: bool end_array()");
9797 static_assert(
9798 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9799 "Missing/invalid function: bool parse_error(std::size_t, const "
9800 "std::string&, const exception&)");
9801};
9802 
9803} // namespace detail
9804NLOHMANN_JSON_NAMESPACE_END
9805 
9806// #include <nlohmann/detail/meta/type_traits.hpp>
9807 
9808// #include <nlohmann/detail/string_concat.hpp>
9809 
9810// #include <nlohmann/detail/value_t.hpp>
9811 
9812 
9813NLOHMANN_JSON_NAMESPACE_BEGIN
9814namespace detail
9815{
9816 
9817/// how to treat CBOR tags
9818enum class cbor_tag_handler_t
9819{
9820 error, ///< throw a parse_error exception in case of a tag
9821 ignore, ///< ignore tags
9822 store ///< store tags as binary type
9823};
9824 
9825/*!
9826@brief determine system byte order
9827 
9828@return true if and only if system's byte order is little endian
9829 
9830@note from https://stackoverflow.com/a/1001328/266378
9831*/
9832static inline bool little_endianness(int num = 1) noexcept
9833{
9834 return *reinterpret_cast<char*>(&num) == 1;
9835}
9836 
9837///////////////////
9838// binary reader //
9839///////////////////
9840 
9841/*!
9842@brief deserialization of CBOR, MessagePack, and UBJSON values
9843*/
9844template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9845class binary_reader
9846{
9847 using number_integer_t = typename BasicJsonType::number_integer_t;
9848 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9849 using number_float_t = typename BasicJsonType::number_float_t;
9850 using string_t = typename BasicJsonType::string_t;
9851 using binary_t = typename BasicJsonType::binary_t;
9852 using json_sax_t = SAX;
9853 using char_type = typename InputAdapterType::char_type;
9854 using char_int_type = typename char_traits<char_type>::int_type;
9855 
9856 public:
9857 /*!
9858 @brief create a binary reader
9859 
9860 @param[in] adapter input adapter to read from
9861 */
9862 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9863 {
9864 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9865 }
9866 
9867 // make class move-only
9868 binary_reader(const binary_reader&) = delete;
9869 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9870 binary_reader& operator=(const binary_reader&) = delete;
9871 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9872 ~binary_reader() = default;
9873 
9874 /*!
9875 @param[in] format the binary format to parse
9876 @param[in] sax_ a SAX event processor
9877 @param[in] strict whether to expect the input to be consumed completed
9878 @param[in] tag_handler how to treat CBOR tags
9879 
9880 @return whether parsing was successful
9881 */
9882 JSON_HEDLEY_NON_NULL(3)
9883 bool sax_parse(const input_format_t format,
9884 json_sax_t* sax_,
9885 const bool strict = true,
9886 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9887 {
9888 sax = sax_;
9889 bool result = false;
9890 
9891 switch (format)
9892 {
9893 case input_format_t::bson:
9894 result = parse_bson_internal();
9895 break;
9896 
9897 case input_format_t::cbor:
9898 result = parse_cbor_internal(true, tag_handler);
9899 break;
9900 
9901 case input_format_t::msgpack:
9902 result = parse_msgpack_internal();
9903 break;
9904 
9905 case input_format_t::ubjson:
9906 case input_format_t::bjdata:
9907 result = parse_ubjson_internal();
9908 break;
9909 
9910 case input_format_t::json: // LCOV_EXCL_LINE
9911 default: // LCOV_EXCL_LINE
9912 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9913 }
9914 
9915 // strict mode: next byte must be EOF
9916 if (result && strict)
9917 {
9918 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9919 {
9920 get_ignore_noop();
9921 }
9922 else
9923 {
9924 get();
9925 }
9926 
9927 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9928 {
9929 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9930 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9931 }
9932 }
9933 
9934 return result;
9935 }
9936 
9937 private:
9938 //////////
9939 // BSON //
9940 //////////
9941 
9942 /*!
9943 @brief Reads in a BSON-object and passes it to the SAX-parser.
9944 @return whether a valid BSON-value was passed to the SAX parser
9945 */
9946 bool parse_bson_internal()
9947 {
9948 std::int32_t document_size{};
9949 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9950 
9951 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
9952 {
9953 return false;
9954 }
9955 
9956 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9957 {
9958 return false;
9959 }
9960 
9961 return sax->end_object();
9962 }
9963 
9964 /*!
9965 @brief Parses a C-style string from the BSON input.
9966 @param[in,out] result A reference to the string variable where the read
9967 string is to be stored.
9968 @return `true` if the \x00-byte indicating the end of the string was
9969 encountered before the EOF; false` indicates an unexpected EOF.
9970 */
9971 bool get_bson_cstr(string_t& result)
9972 {
9973 auto out = std::back_inserter(result);
9974 while (true)
9975 {
9976 get();
9977 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9978 {
9979 return false;
9980 }
9981 if (current == 0x00)
9982 {
9983 return true;
9984 }
9985 *out++ = static_cast<typename string_t::value_type>(current);
9986 }
9987 }
9988 
9989 /*!
9990 @brief Parses a zero-terminated string of length @a len from the BSON
9991 input.
9992 @param[in] len The length (including the zero-byte at the end) of the
9993 string to be read.
9994 @param[in,out] result A reference to the string variable where the read
9995 string is to be stored.
9996 @tparam NumberType The type of the length @a len
9997 @pre len >= 1
9998 @return `true` if the string was successfully parsed
9999 */
10000 template<typename NumberType>
10001 bool get_bson_string(const NumberType len, string_t& result)
10002 {
10003 if (JSON_HEDLEY_UNLIKELY(len < 1))
10004 {
10005 auto last_token = get_token_string();
10006 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10007 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10008 }
10009 
10010 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10011 }
10012 
10013 /*!
10014 @brief Parses a byte array input of length @a len from the BSON input.
10015 @param[in] len The length of the byte array to be read.
10016 @param[in,out] result A reference to the binary variable where the read
10017 array is to be stored.
10018 @tparam NumberType The type of the length @a len
10019 @pre len >= 0
10020 @return `true` if the byte array was successfully parsed
10021 */
10022 template<typename NumberType>
10023 bool get_bson_binary(const NumberType len, binary_t& result)
10024 {
10025 if (JSON_HEDLEY_UNLIKELY(len < 0))
10026 {
10027 auto last_token = get_token_string();
10028 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10029 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10030 }
10031 
10032 // All BSON binary values have a subtype
10033 std::uint8_t subtype{};
10034 get_number<std::uint8_t>(input_format_t::bson, subtype);
10035 result.set_subtype(subtype);
10036 
10037 return get_binary(input_format_t::bson, len, result);
10038 }
10039 
10040 /*!
10041 @brief Read a BSON document element of the given @a element_type.
10042 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
10043 @param[in] element_type_parse_position The position in the input stream,
10044 where the `element_type` was read.
10045 @warning Not all BSON element types are supported yet. An unsupported
10046 @a element_type will give rise to a parse_error.114:
10047 Unsupported BSON record type 0x...
10048 @return whether a valid BSON-object/array was passed to the SAX parser
10049 */
10050 bool parse_bson_element_internal(const char_int_type element_type,
10051 const std::size_t element_type_parse_position)
10052 {
10053 switch (element_type)
10054 {
10055 case 0x01: // double
10056 {
10057 double number{};
10058 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10059 }
10060 
10061 case 0x02: // string
10062 {
10063 std::int32_t len{};
10064 string_t value;
10065 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10066 }
10067 
10068 case 0x03: // object
10069 {
10070 return parse_bson_internal();
10071 }
10072 
10073 case 0x04: // array
10074 {
10075 return parse_bson_array();
10076 }
10077 
10078 case 0x05: // binary
10079 {
10080 std::int32_t len{};
10081 binary_t value;
10082 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10083 }
10084 
10085 case 0x08: // boolean
10086 {
10087 return sax->boolean(get() != 0);
10088 }
10089 
10090 case 0x0A: // null
10091 {
10092 return sax->null();
10093 }
10094 
10095 case 0x10: // int32
10096 {
10097 std::int32_t value{};
10098 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10099 }
10100 
10101 case 0x12: // int64
10102 {
10103 std::int64_t value{};
10104 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10105 }
10106 
10107 case 0x11: // uint64
10108 {
10109 std::uint64_t value{};
10110 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10111 }
10112 
10113 default: // anything else not supported (yet)
10114 {
10115 std::array<char, 3> cr{{}};
10116 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10117 const std::string cr_str{cr.data()};
10118 return sax->parse_error(element_type_parse_position, cr_str,
10119 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10120 }
10121 }
10122 }
10123 
10124 /*!
10125 @brief Read a BSON element list (as specified in the BSON-spec)
10126 
10127 The same binary layout is used for objects and arrays, hence it must be
10128 indicated with the argument @a is_array which one is expected
10129 (true --> array, false --> object).
10130 
10131 @param[in] is_array Determines if the element list being read is to be
10132 treated as an object (@a is_array == false), or as an
10133 array (@a is_array == true).
10134 @return whether a valid BSON-object/array was passed to the SAX parser
10135 */
10136 bool parse_bson_element_list(const bool is_array)
10137 {
10138 string_t key;
10139 
10140 while (auto element_type = get())
10141 {
10142 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10143 {
10144 return false;
10145 }
10146 
10147 const std::size_t element_type_parse_position = chars_read;
10148 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10149 {
10150 return false;
10151 }
10152 
10153 if (!is_array && !sax->key(key))
10154 {
10155 return false;
10156 }
10157 
10158 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10159 {
10160 return false;
10161 }
10162 
10163 // get_bson_cstr only appends
10164 key.clear();
10165 }
10166 
10167 return true;
10168 }
10169 
10170 /*!
10171 @brief Reads an array from the BSON input and passes it to the SAX-parser.
10172 @return whether a valid BSON-array was passed to the SAX parser
10173 */
10174 bool parse_bson_array()
10175 {
10176 std::int32_t document_size{};
10177 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10178 
10179 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10180 {
10181 return false;
10182 }
10183 
10184 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10185 {
10186 return false;
10187 }
10188 
10189 return sax->end_array();
10190 }
10191 
10192 //////////
10193 // CBOR //
10194 //////////
10195 
10196 /*!
10197 @param[in] get_char whether a new character should be retrieved from the
10198 input (true) or whether the last read character should
10199 be considered instead (false)
10200 @param[in] tag_handler how CBOR tags should be treated
10201 
10202 @return whether a valid CBOR value was passed to the SAX parser
10203 */
10204 bool parse_cbor_internal(const bool get_char,
10205 const cbor_tag_handler_t tag_handler)
10206 {
10207 switch (get_char ? get() : current)
10208 {
10209 // EOF
10210 case char_traits<char_type>::eof():
10211 return unexpect_eof(input_format_t::cbor, "value");
10212 
10213 // Integer 0x00..0x17 (0..23)
10214 case 0x00:
10215 case 0x01:
10216 case 0x02:
10217 case 0x03:
10218 case 0x04:
10219 case 0x05:
10220 case 0x06:
10221 case 0x07:
10222 case 0x08:
10223 case 0x09:
10224 case 0x0A:
10225 case 0x0B:
10226 case 0x0C:
10227 case 0x0D:
10228 case 0x0E:
10229 case 0x0F:
10230 case 0x10:
10231 case 0x11:
10232 case 0x12:
10233 case 0x13:
10234 case 0x14:
10235 case 0x15:
10236 case 0x16:
10237 case 0x17:
10238 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10239 
10240 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10241 {
10242 std::uint8_t number{};
10243 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10244 }
10245 
10246 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10247 {
10248 std::uint16_t number{};
10249 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10250 }
10251 
10252 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10253 {
10254 std::uint32_t number{};
10255 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10256 }
10257 
10258 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10259 {
10260 std::uint64_t number{};
10261 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10262 }
10263 
10264 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10265 case 0x20:
10266 case 0x21:
10267 case 0x22:
10268 case 0x23:
10269 case 0x24:
10270 case 0x25:
10271 case 0x26:
10272 case 0x27:
10273 case 0x28:
10274 case 0x29:
10275 case 0x2A:
10276 case 0x2B:
10277 case 0x2C:
10278 case 0x2D:
10279 case 0x2E:
10280 case 0x2F:
10281 case 0x30:
10282 case 0x31:
10283 case 0x32:
10284 case 0x33:
10285 case 0x34:
10286 case 0x35:
10287 case 0x36:
10288 case 0x37:
10289 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10290 
10291 case 0x38: // Negative integer (one-byte uint8_t follows)
10292 {
10293 std::uint8_t number{};
10294 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10295 }
10296 
10297 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10298 {
10299 std::uint16_t number{};
10300 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10301 }
10302 
10303 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10304 {
10305 std::uint32_t number{};
10306 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10307 }
10308 
10309 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10310 {
10311 std::uint64_t number{};
10312 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10313 - static_cast<number_integer_t>(number));
10314 }
10315 
10316 // Binary data (0x00..0x17 bytes follow)
10317 case 0x40:
10318 case 0x41:
10319 case 0x42:
10320 case 0x43:
10321 case 0x44:
10322 case 0x45:
10323 case 0x46:
10324 case 0x47:
10325 case 0x48:
10326 case 0x49:
10327 case 0x4A:
10328 case 0x4B:
10329 case 0x4C:
10330 case 0x4D:
10331 case 0x4E:
10332 case 0x4F:
10333 case 0x50:
10334 case 0x51:
10335 case 0x52:
10336 case 0x53:
10337 case 0x54:
10338 case 0x55:
10339 case 0x56:
10340 case 0x57:
10341 case 0x58: // Binary data (one-byte uint8_t for n follows)
10342 case 0x59: // Binary data (two-byte uint16_t for n follow)
10343 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10344 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10345 case 0x5F: // Binary data (indefinite length)
10346 {
10347 binary_t b;
10348 return get_cbor_binary(b) && sax->binary(b);
10349 }
10350 
10351 // UTF-8 string (0x00..0x17 bytes follow)
10352 case 0x60:
10353 case 0x61:
10354 case 0x62:
10355 case 0x63:
10356 case 0x64:
10357 case 0x65:
10358 case 0x66:
10359 case 0x67:
10360 case 0x68:
10361 case 0x69:
10362 case 0x6A:
10363 case 0x6B:
10364 case 0x6C:
10365 case 0x6D:
10366 case 0x6E:
10367 case 0x6F:
10368 case 0x70:
10369 case 0x71:
10370 case 0x72:
10371 case 0x73:
10372 case 0x74:
10373 case 0x75:
10374 case 0x76:
10375 case 0x77:
10376 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10377 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10378 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10379 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10380 case 0x7F: // UTF-8 string (indefinite length)
10381 {
10382 string_t s;
10383 return get_cbor_string(s) && sax->string(s);
10384 }
10385 
10386 // array (0x00..0x17 data items follow)
10387 case 0x80:
10388 case 0x81:
10389 case 0x82:
10390 case 0x83:
10391 case 0x84:
10392 case 0x85:
10393 case 0x86:
10394 case 0x87:
10395 case 0x88:
10396 case 0x89:
10397 case 0x8A:
10398 case 0x8B:
10399 case 0x8C:
10400 case 0x8D:
10401 case 0x8E:
10402 case 0x8F:
10403 case 0x90:
10404 case 0x91:
10405 case 0x92:
10406 case 0x93:
10407 case 0x94:
10408 case 0x95:
10409 case 0x96:
10410 case 0x97:
10411 return get_cbor_array(
10412 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10413 
10414 case 0x98: // array (one-byte uint8_t for n follows)
10415 {
10416 std::uint8_t len{};
10417 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10418 }
10419 
10420 case 0x99: // array (two-byte uint16_t for n follow)
10421 {
10422 std::uint16_t len{};
10423 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10424 }
10425 
10426 case 0x9A: // array (four-byte uint32_t for n follow)
10427 {
10428 std::uint32_t len{};
10429 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10430 }
10431 
10432 case 0x9B: // array (eight-byte uint64_t for n follow)
10433 {
10434 std::uint64_t len{};
10435 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10436 }
10437 
10438 case 0x9F: // array (indefinite length)
10439 return get_cbor_array(detail::unknown_size(), tag_handler);
10440 
10441 // map (0x00..0x17 pairs of data items follow)
10442 case 0xA0:
10443 case 0xA1:
10444 case 0xA2:
10445 case 0xA3:
10446 case 0xA4:
10447 case 0xA5:
10448 case 0xA6:
10449 case 0xA7:
10450 case 0xA8:
10451 case 0xA9:
10452 case 0xAA:
10453 case 0xAB:
10454 case 0xAC:
10455 case 0xAD:
10456 case 0xAE:
10457 case 0xAF:
10458 case 0xB0:
10459 case 0xB1:
10460 case 0xB2:
10461 case 0xB3:
10462 case 0xB4:
10463 case 0xB5:
10464 case 0xB6:
10465 case 0xB7:
10466 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10467 
10468 case 0xB8: // map (one-byte uint8_t for n follows)
10469 {
10470 std::uint8_t len{};
10471 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10472 }
10473 
10474 case 0xB9: // map (two-byte uint16_t for n follow)
10475 {
10476 std::uint16_t len{};
10477 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10478 }
10479 
10480 case 0xBA: // map (four-byte uint32_t for n follow)
10481 {
10482 std::uint32_t len{};
10483 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10484 }
10485 
10486 case 0xBB: // map (eight-byte uint64_t for n follow)
10487 {
10488 std::uint64_t len{};
10489 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10490 }
10491 
10492 case 0xBF: // map (indefinite length)
10493 return get_cbor_object(detail::unknown_size(), tag_handler);
10494 
10495 case 0xC6: // tagged item
10496 case 0xC7:
10497 case 0xC8:
10498 case 0xC9:
10499 case 0xCA:
10500 case 0xCB:
10501 case 0xCC:
10502 case 0xCD:
10503 case 0xCE:
10504 case 0xCF:
10505 case 0xD0:
10506 case 0xD1:
10507 case 0xD2:
10508 case 0xD3:
10509 case 0xD4:
10510 case 0xD8: // tagged item (1 bytes follow)
10511 case 0xD9: // tagged item (2 bytes follow)
10512 case 0xDA: // tagged item (4 bytes follow)
10513 case 0xDB: // tagged item (8 bytes follow)
10514 {
10515 switch (tag_handler)
10516 {
10517 case cbor_tag_handler_t::error:
10518 {
10519 auto last_token = get_token_string();
10520 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10521 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10522 }
10523 
10524 case cbor_tag_handler_t::ignore:
10525 {
10526 // ignore binary subtype
10527 switch (current)
10528 {
10529 case 0xD8:
10530 {
10531 std::uint8_t subtype_to_ignore{};
10532 get_number(input_format_t::cbor, subtype_to_ignore);
10533 break;
10534 }
10535 case 0xD9:
10536 {
10537 std::uint16_t subtype_to_ignore{};
10538 get_number(input_format_t::cbor, subtype_to_ignore);
10539 break;
10540 }
10541 case 0xDA:
10542 {
10543 std::uint32_t subtype_to_ignore{};
10544 get_number(input_format_t::cbor, subtype_to_ignore);
10545 break;
10546 }
10547 case 0xDB:
10548 {
10549 std::uint64_t subtype_to_ignore{};
10550 get_number(input_format_t::cbor, subtype_to_ignore);
10551 break;
10552 }
10553 default:
10554 break;
10555 }
10556 return parse_cbor_internal(true, tag_handler);
10557 }
10558 
10559 case cbor_tag_handler_t::store:
10560 {
10561 binary_t b;
10562 // use binary subtype and store in binary container
10563 switch (current)
10564 {
10565 case 0xD8:
10566 {
10567 std::uint8_t subtype{};
10568 get_number(input_format_t::cbor, subtype);
10569 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10570 break;
10571 }
10572 case 0xD9:
10573 {
10574 std::uint16_t subtype{};
10575 get_number(input_format_t::cbor, subtype);
10576 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10577 break;
10578 }
10579 case 0xDA:
10580 {
10581 std::uint32_t subtype{};
10582 get_number(input_format_t::cbor, subtype);
10583 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10584 break;
10585 }
10586 case 0xDB:
10587 {
10588 std::uint64_t subtype{};
10589 get_number(input_format_t::cbor, subtype);
10590 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10591 break;
10592 }
10593 default:
10594 return parse_cbor_internal(true, tag_handler);
10595 }
10596 get();
10597 return get_cbor_binary(b) && sax->binary(b);
10598 }
10599 
10600 default: // LCOV_EXCL_LINE
10601 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10602 return false; // LCOV_EXCL_LINE
10603 }
10604 }
10605 
10606 case 0xF4: // false
10607 return sax->boolean(false);
10608 
10609 case 0xF5: // true
10610 return sax->boolean(true);
10611 
10612 case 0xF6: // null
10613 return sax->null();
10614 
10615 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10616 {
10617 const auto byte1_raw = get();
10618 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10619 {
10620 return false;
10621 }
10622 const auto byte2_raw = get();
10623 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10624 {
10625 return false;
10626 }
10627 
10628 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10629 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10630 
10631 // code from RFC 7049, Appendix D, Figure 3:
10632 // As half-precision floating-point numbers were only added
10633 // to IEEE 754 in 2008, today's programming platforms often
10634 // still only have limited support for them. It is very
10635 // easy to include at least decoding support for them even
10636 // without such support. An example of a small decoder for
10637 // half-precision floating-point numbers in the C language
10638 // is shown in Fig. 3.
10639 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10640 const double val = [&half]
10641 {
10642 const int exp = (half >> 10u) & 0x1Fu;
10643 const unsigned int mant = half & 0x3FFu;
10644 JSON_ASSERT(0 <= exp&& exp <= 32);
10645 JSON_ASSERT(mant <= 1024);
10646 switch (exp)
10647 {
10648 case 0:
10649 return std::ldexp(mant, -24);
10650 case 31:
10651 return (mant == 0)
10652 ? std::numeric_limits<double>::infinity()
10653 : std::numeric_limits<double>::quiet_NaN();
10654 default:
10655 return std::ldexp(mant + 1024, exp - 25);
10656 }
10657 }();
10658 return sax->number_float((half & 0x8000u) != 0
10659 ? static_cast<number_float_t>(-val)
10660 : static_cast<number_float_t>(val), "");
10661 }
10662 
10663 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10664 {
10665 float number{};
10666 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10667 }
10668 
10669 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10670 {
10671 double number{};
10672 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10673 }
10674 
10675 default: // anything else (0xFF is handled inside the other types)
10676 {
10677 auto last_token = get_token_string();
10678 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10679 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10680 }
10681 }
10682 }
10683 
10684 /*!
10685 @brief reads a CBOR string
10686 
10687 This function first reads starting bytes to determine the expected
10688 string length and then copies this number of bytes into a string.
10689 Additionally, CBOR's strings with indefinite lengths are supported.
10690 
10691 @param[out] result created string
10692 
10693 @return whether string creation completed
10694 */
10695 bool get_cbor_string(string_t& result)
10696 {
10697 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10698 {
10699 return false;
10700 }
10701 
10702 switch (current)
10703 {
10704 // UTF-8 string (0x00..0x17 bytes follow)
10705 case 0x60:
10706 case 0x61:
10707 case 0x62:
10708 case 0x63:
10709 case 0x64:
10710 case 0x65:
10711 case 0x66:
10712 case 0x67:
10713 case 0x68:
10714 case 0x69:
10715 case 0x6A:
10716 case 0x6B:
10717 case 0x6C:
10718 case 0x6D:
10719 case 0x6E:
10720 case 0x6F:
10721 case 0x70:
10722 case 0x71:
10723 case 0x72:
10724 case 0x73:
10725 case 0x74:
10726 case 0x75:
10727 case 0x76:
10728 case 0x77:
10729 {
10730 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10731 }
10732 
10733 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10734 {
10735 std::uint8_t len{};
10736 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10737 }
10738 
10739 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10740 {
10741 std::uint16_t len{};
10742 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10743 }
10744 
10745 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10746 {
10747 std::uint32_t len{};
10748 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10749 }
10750 
10751 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10752 {
10753 std::uint64_t len{};
10754 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10755 }
10756 
10757 case 0x7F: // UTF-8 string (indefinite length)
10758 {
10759 while (get() != 0xFF)
10760 {
10761 string_t chunk;
10762 if (!get_cbor_string(chunk))
10763 {
10764 return false;
10765 }
10766 result.append(chunk);
10767 }
10768 return true;
10769 }
10770 
10771 default:
10772 {
10773 auto last_token = get_token_string();
10774 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10775 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10776 }
10777 }
10778 }
10779 
10780 /*!
10781 @brief reads a CBOR byte array
10782 
10783 This function first reads starting bytes to determine the expected
10784 byte array length and then copies this number of bytes into the byte array.
10785 Additionally, CBOR's byte arrays with indefinite lengths are supported.
10786 
10787 @param[out] result created byte array
10788 
10789 @return whether byte array creation completed
10790 */
10791 bool get_cbor_binary(binary_t& result)
10792 {
10793 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10794 {
10795 return false;
10796 }
10797 
10798 switch (current)
10799 {
10800 // Binary data (0x00..0x17 bytes follow)
10801 case 0x40:
10802 case 0x41:
10803 case 0x42:
10804 case 0x43:
10805 case 0x44:
10806 case 0x45:
10807 case 0x46:
10808 case 0x47:
10809 case 0x48:
10810 case 0x49:
10811 case 0x4A:
10812 case 0x4B:
10813 case 0x4C:
10814 case 0x4D:
10815 case 0x4E:
10816 case 0x4F:
10817 case 0x50:
10818 case 0x51:
10819 case 0x52:
10820 case 0x53:
10821 case 0x54:
10822 case 0x55:
10823 case 0x56:
10824 case 0x57:
10825 {
10826 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10827 }
10828 
10829 case 0x58: // Binary data (one-byte uint8_t for n follows)
10830 {
10831 std::uint8_t len{};
10832 return get_number(input_format_t::cbor, len) &&
10833 get_binary(input_format_t::cbor, len, result);
10834 }
10835 
10836 case 0x59: // Binary data (two-byte uint16_t for n follow)
10837 {
10838 std::uint16_t len{};
10839 return get_number(input_format_t::cbor, len) &&
10840 get_binary(input_format_t::cbor, len, result);
10841 }
10842 
10843 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10844 {
10845 std::uint32_t len{};
10846 return get_number(input_format_t::cbor, len) &&
10847 get_binary(input_format_t::cbor, len, result);
10848 }
10849 
10850 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10851 {
10852 std::uint64_t len{};
10853 return get_number(input_format_t::cbor, len) &&
10854 get_binary(input_format_t::cbor, len, result);
10855 }
10856 
10857 case 0x5F: // Binary data (indefinite length)
10858 {
10859 while (get() != 0xFF)
10860 {
10861 binary_t chunk;
10862 if (!get_cbor_binary(chunk))
10863 {
10864 return false;
10865 }
10866 result.insert(result.end(), chunk.begin(), chunk.end());
10867 }
10868 return true;
10869 }
10870 
10871 default:
10872 {
10873 auto last_token = get_token_string();
10874 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10875 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));
10876 }
10877 }
10878 }
10879 
10880 /*!
10881 @param[in] len the length of the array or detail::unknown_size() for an
10882 array of indefinite size
10883 @param[in] tag_handler how CBOR tags should be treated
10884 @return whether array creation completed
10885 */
10886 bool get_cbor_array(const std::size_t len,
10887 const cbor_tag_handler_t tag_handler)
10888 {
10889 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10890 {
10891 return false;
10892 }
10893 
10894 if (len != detail::unknown_size())
10895 {
10896 for (std::size_t i = 0; i < len; ++i)
10897 {
10898 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10899 {
10900 return false;
10901 }
10902 }
10903 }
10904 else
10905 {
10906 while (get() != 0xFF)
10907 {
10908 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10909 {
10910 return false;
10911 }
10912 }
10913 }
10914 
10915 return sax->end_array();
10916 }
10917 
10918 /*!
10919 @param[in] len the length of the object or detail::unknown_size() for an
10920 object of indefinite size
10921 @param[in] tag_handler how CBOR tags should be treated
10922 @return whether object creation completed
10923 */
10924 bool get_cbor_object(const std::size_t len,
10925 const cbor_tag_handler_t tag_handler)
10926 {
10927 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10928 {
10929 return false;
10930 }
10931 
10932 if (len != 0)
10933 {
10934 string_t key;
10935 if (len != detail::unknown_size())
10936 {
10937 for (std::size_t i = 0; i < len; ++i)
10938 {
10939 get();
10940 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10941 {
10942 return false;
10943 }
10944 
10945 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10946 {
10947 return false;
10948 }
10949 key.clear();
10950 }
10951 }
10952 else
10953 {
10954 while (get() != 0xFF)
10955 {
10956 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10957 {
10958 return false;
10959 }
10960 
10961 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10962 {
10963 return false;
10964 }
10965 key.clear();
10966 }
10967 }
10968 }
10969 
10970 return sax->end_object();
10971 }
10972 
10973 /////////////
10974 // MsgPack //
10975 /////////////
10976 
10977 /*!
10978 @return whether a valid MessagePack value was passed to the SAX parser
10979 */
10980 bool parse_msgpack_internal()
10981 {
10982 switch (get())
10983 {
10984 // EOF
10985 case char_traits<char_type>::eof():
10986 return unexpect_eof(input_format_t::msgpack, "value");
10987 
10988 // positive fixint
10989 case 0x00:
10990 case 0x01:
10991 case 0x02:
10992 case 0x03:
10993 case 0x04:
10994 case 0x05:
10995 case 0x06:
10996 case 0x07:
10997 case 0x08:
10998 case 0x09:
10999 case 0x0A:
11000 case 0x0B:
11001 case 0x0C:
11002 case 0x0D:
11003 case 0x0E:
11004 case 0x0F:
11005 case 0x10:
11006 case 0x11:
11007 case 0x12:
11008 case 0x13:
11009 case 0x14:
11010 case 0x15:
11011 case 0x16:
11012 case 0x17:
11013 case 0x18:
11014 case 0x19:
11015 case 0x1A:
11016 case 0x1B:
11017 case 0x1C:
11018 case 0x1D:
11019 case 0x1E:
11020 case 0x1F:
11021 case 0x20:
11022 case 0x21:
11023 case 0x22:
11024 case 0x23:
11025 case 0x24:
11026 case 0x25:
11027 case 0x26:
11028 case 0x27:
11029 case 0x28:
11030 case 0x29:
11031 case 0x2A:
11032 case 0x2B:
11033 case 0x2C:
11034 case 0x2D:
11035 case 0x2E:
11036 case 0x2F:
11037 case 0x30:
11038 case 0x31:
11039 case 0x32:
11040 case 0x33:
11041 case 0x34:
11042 case 0x35:
11043 case 0x36:
11044 case 0x37:
11045 case 0x38:
11046 case 0x39:
11047 case 0x3A:
11048 case 0x3B:
11049 case 0x3C:
11050 case 0x3D:
11051 case 0x3E:
11052 case 0x3F:
11053 case 0x40:
11054 case 0x41:
11055 case 0x42:
11056 case 0x43:
11057 case 0x44:
11058 case 0x45:
11059 case 0x46:
11060 case 0x47:
11061 case 0x48:
11062 case 0x49:
11063 case 0x4A:
11064 case 0x4B:
11065 case 0x4C:
11066 case 0x4D:
11067 case 0x4E:
11068 case 0x4F:
11069 case 0x50:
11070 case 0x51:
11071 case 0x52:
11072 case 0x53:
11073 case 0x54:
11074 case 0x55:
11075 case 0x56:
11076 case 0x57:
11077 case 0x58:
11078 case 0x59:
11079 case 0x5A:
11080 case 0x5B:
11081 case 0x5C:
11082 case 0x5D:
11083 case 0x5E:
11084 case 0x5F:
11085 case 0x60:
11086 case 0x61:
11087 case 0x62:
11088 case 0x63:
11089 case 0x64:
11090 case 0x65:
11091 case 0x66:
11092 case 0x67:
11093 case 0x68:
11094 case 0x69:
11095 case 0x6A:
11096 case 0x6B:
11097 case 0x6C:
11098 case 0x6D:
11099 case 0x6E:
11100 case 0x6F:
11101 case 0x70:
11102 case 0x71:
11103 case 0x72:
11104 case 0x73:
11105 case 0x74:
11106 case 0x75:
11107 case 0x76:
11108 case 0x77:
11109 case 0x78:
11110 case 0x79:
11111 case 0x7A:
11112 case 0x7B:
11113 case 0x7C:
11114 case 0x7D:
11115 case 0x7E:
11116 case 0x7F:
11117 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11118 
11119 // fixmap
11120 case 0x80:
11121 case 0x81:
11122 case 0x82:
11123 case 0x83:
11124 case 0x84:
11125 case 0x85:
11126 case 0x86:
11127 case 0x87:
11128 case 0x88:
11129 case 0x89:
11130 case 0x8A:
11131 case 0x8B:
11132 case 0x8C:
11133 case 0x8D:
11134 case 0x8E:
11135 case 0x8F:
11136 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11137 
11138 // fixarray
11139 case 0x90:
11140 case 0x91:
11141 case 0x92:
11142 case 0x93:
11143 case 0x94:
11144 case 0x95:
11145 case 0x96:
11146 case 0x97:
11147 case 0x98:
11148 case 0x99:
11149 case 0x9A:
11150 case 0x9B:
11151 case 0x9C:
11152 case 0x9D:
11153 case 0x9E:
11154 case 0x9F:
11155 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11156 
11157 // fixstr
11158 case 0xA0:
11159 case 0xA1:
11160 case 0xA2:
11161 case 0xA3:
11162 case 0xA4:
11163 case 0xA5:
11164 case 0xA6:
11165 case 0xA7:
11166 case 0xA8:
11167 case 0xA9:
11168 case 0xAA:
11169 case 0xAB:
11170 case 0xAC:
11171 case 0xAD:
11172 case 0xAE:
11173 case 0xAF:
11174 case 0xB0:
11175 case 0xB1:
11176 case 0xB2:
11177 case 0xB3:
11178 case 0xB4:
11179 case 0xB5:
11180 case 0xB6:
11181 case 0xB7:
11182 case 0xB8:
11183 case 0xB9:
11184 case 0xBA:
11185 case 0xBB:
11186 case 0xBC:
11187 case 0xBD:
11188 case 0xBE:
11189 case 0xBF:
11190 case 0xD9: // str 8
11191 case 0xDA: // str 16
11192 case 0xDB: // str 32
11193 {
11194 string_t s;
11195 return get_msgpack_string(s) && sax->string(s);
11196 }
11197 
11198 case 0xC0: // nil
11199 return sax->null();
11200 
11201 case 0xC2: // false
11202 return sax->boolean(false);
11203 
11204 case 0xC3: // true
11205 return sax->boolean(true);
11206 
11207 case 0xC4: // bin 8
11208 case 0xC5: // bin 16
11209 case 0xC6: // bin 32
11210 case 0xC7: // ext 8
11211 case 0xC8: // ext 16
11212 case 0xC9: // ext 32
11213 case 0xD4: // fixext 1
11214 case 0xD5: // fixext 2
11215 case 0xD6: // fixext 4
11216 case 0xD7: // fixext 8
11217 case 0xD8: // fixext 16
11218 {
11219 binary_t b;
11220 return get_msgpack_binary(b) && sax->binary(b);
11221 }
11222 
11223 case 0xCA: // float 32
11224 {
11225 float number{};
11226 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11227 }
11228 
11229 case 0xCB: // float 64
11230 {
11231 double number{};
11232 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11233 }
11234 
11235 case 0xCC: // uint 8
11236 {
11237 std::uint8_t number{};
11238 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11239 }
11240 
11241 case 0xCD: // uint 16
11242 {
11243 std::uint16_t number{};
11244 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11245 }
11246 
11247 case 0xCE: // uint 32
11248 {
11249 std::uint32_t number{};
11250 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11251 }
11252 
11253 case 0xCF: // uint 64
11254 {
11255 std::uint64_t number{};
11256 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11257 }
11258 
11259 case 0xD0: // int 8
11260 {
11261 std::int8_t number{};
11262 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11263 }
11264 
11265 case 0xD1: // int 16
11266 {
11267 std::int16_t number{};
11268 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11269 }
11270 
11271 case 0xD2: // int 32
11272 {
11273 std::int32_t number{};
11274 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11275 }
11276 
11277 case 0xD3: // int 64
11278 {
11279 std::int64_t number{};
11280 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11281 }
11282 
11283 case 0xDC: // array 16
11284 {
11285 std::uint16_t len{};
11286 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11287 }
11288 
11289 case 0xDD: // array 32
11290 {
11291 std::uint32_t len{};
11292 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11293 }
11294 
11295 case 0xDE: // map 16
11296 {
11297 std::uint16_t len{};
11298 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11299 }
11300 
11301 case 0xDF: // map 32
11302 {
11303 std::uint32_t len{};
11304 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11305 }
11306 
11307 // negative fixint
11308 case 0xE0:
11309 case 0xE1:
11310 case 0xE2:
11311 case 0xE3:
11312 case 0xE4:
11313 case 0xE5:
11314 case 0xE6:
11315 case 0xE7:
11316 case 0xE8:
11317 case 0xE9:
11318 case 0xEA:
11319 case 0xEB:
11320 case 0xEC:
11321 case 0xED:
11322 case 0xEE:
11323 case 0xEF:
11324 case 0xF0:
11325 case 0xF1:
11326 case 0xF2:
11327 case 0xF3:
11328 case 0xF4:
11329 case 0xF5:
11330 case 0xF6:
11331 case 0xF7:
11332 case 0xF8:
11333 case 0xF9:
11334 case 0xFA:
11335 case 0xFB:
11336 case 0xFC:
11337 case 0xFD:
11338 case 0xFE:
11339 case 0xFF:
11340 return sax->number_integer(static_cast<std::int8_t>(current));
11341 
11342 default: // anything else
11343 {
11344 auto last_token = get_token_string();
11345 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11346 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11347 }
11348 }
11349 }
11350 
11351 /*!
11352 @brief reads a MessagePack string
11353 
11354 This function first reads starting bytes to determine the expected
11355 string length and then copies this number of bytes into a string.
11356 
11357 @param[out] result created string
11358 
11359 @return whether string creation completed
11360 */
11361 bool get_msgpack_string(string_t& result)
11362 {
11363 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11364 {
11365 return false;
11366 }
11367 
11368 switch (current)
11369 {
11370 // fixstr
11371 case 0xA0:
11372 case 0xA1:
11373 case 0xA2:
11374 case 0xA3:
11375 case 0xA4:
11376 case 0xA5:
11377 case 0xA6:
11378 case 0xA7:
11379 case 0xA8:
11380 case 0xA9:
11381 case 0xAA:
11382 case 0xAB:
11383 case 0xAC:
11384 case 0xAD:
11385 case 0xAE:
11386 case 0xAF:
11387 case 0xB0:
11388 case 0xB1:
11389 case 0xB2:
11390 case 0xB3:
11391 case 0xB4:
11392 case 0xB5:
11393 case 0xB6:
11394 case 0xB7:
11395 case 0xB8:
11396 case 0xB9:
11397 case 0xBA:
11398 case 0xBB:
11399 case 0xBC:
11400 case 0xBD:
11401 case 0xBE:
11402 case 0xBF:
11403 {
11404 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11405 }
11406 
11407 case 0xD9: // str 8
11408 {
11409 std::uint8_t len{};
11410 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11411 }
11412 
11413 case 0xDA: // str 16
11414 {
11415 std::uint16_t len{};
11416 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11417 }
11418 
11419 case 0xDB: // str 32
11420 {
11421 std::uint32_t len{};
11422 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11423 }
11424 
11425 default:
11426 {
11427 auto last_token = get_token_string();
11428 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11429 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11430 }
11431 }
11432 }
11433 
11434 /*!
11435 @brief reads a MessagePack byte array
11436 
11437 This function first reads starting bytes to determine the expected
11438 byte array length and then copies this number of bytes into a byte array.
11439 
11440 @param[out] result created byte array
11441 
11442 @return whether byte array creation completed
11443 */
11444 bool get_msgpack_binary(binary_t& result)
11445 {
11446 // helper function to set the subtype
11447 auto assign_and_return_true = [&result](std::int8_t subtype)
11448 {
11449 result.set_subtype(static_cast<std::uint8_t>(subtype));
11450 return true;
11451 };
11452 
11453 switch (current)
11454 {
11455 case 0xC4: // bin 8
11456 {
11457 std::uint8_t len{};
11458 return get_number(input_format_t::msgpack, len) &&
11459 get_binary(input_format_t::msgpack, len, result);
11460 }
11461 
11462 case 0xC5: // bin 16
11463 {
11464 std::uint16_t len{};
11465 return get_number(input_format_t::msgpack, len) &&
11466 get_binary(input_format_t::msgpack, len, result);
11467 }
11468 
11469 case 0xC6: // bin 32
11470 {
11471 std::uint32_t len{};
11472 return get_number(input_format_t::msgpack, len) &&
11473 get_binary(input_format_t::msgpack, len, result);
11474 }
11475 
11476 case 0xC7: // ext 8
11477 {
11478 std::uint8_t len{};
11479 std::int8_t subtype{};
11480 return get_number(input_format_t::msgpack, len) &&
11481 get_number(input_format_t::msgpack, subtype) &&
11482 get_binary(input_format_t::msgpack, len, result) &&
11483 assign_and_return_true(subtype);
11484 }
11485 
11486 case 0xC8: // ext 16
11487 {
11488 std::uint16_t len{};
11489 std::int8_t subtype{};
11490 return get_number(input_format_t::msgpack, len) &&
11491 get_number(input_format_t::msgpack, subtype) &&
11492 get_binary(input_format_t::msgpack, len, result) &&
11493 assign_and_return_true(subtype);
11494 }
11495 
11496 case 0xC9: // ext 32
11497 {
11498 std::uint32_t len{};
11499 std::int8_t subtype{};
11500 return get_number(input_format_t::msgpack, len) &&
11501 get_number(input_format_t::msgpack, subtype) &&
11502 get_binary(input_format_t::msgpack, len, result) &&
11503 assign_and_return_true(subtype);
11504 }
11505 
11506 case 0xD4: // fixext 1
11507 {
11508 std::int8_t subtype{};
11509 return get_number(input_format_t::msgpack, subtype) &&
11510 get_binary(input_format_t::msgpack, 1, result) &&
11511 assign_and_return_true(subtype);
11512 }
11513 
11514 case 0xD5: // fixext 2
11515 {
11516 std::int8_t subtype{};
11517 return get_number(input_format_t::msgpack, subtype) &&
11518 get_binary(input_format_t::msgpack, 2, result) &&
11519 assign_and_return_true(subtype);
11520 }
11521 
11522 case 0xD6: // fixext 4
11523 {
11524 std::int8_t subtype{};
11525 return get_number(input_format_t::msgpack, subtype) &&
11526 get_binary(input_format_t::msgpack, 4, result) &&
11527 assign_and_return_true(subtype);
11528 }
11529 
11530 case 0xD7: // fixext 8
11531 {
11532 std::int8_t subtype{};
11533 return get_number(input_format_t::msgpack, subtype) &&
11534 get_binary(input_format_t::msgpack, 8, result) &&
11535 assign_and_return_true(subtype);
11536 }
11537 
11538 case 0xD8: // fixext 16
11539 {
11540 std::int8_t subtype{};
11541 return get_number(input_format_t::msgpack, subtype) &&
11542 get_binary(input_format_t::msgpack, 16, result) &&
11543 assign_and_return_true(subtype);
11544 }
11545 
11546 default: // LCOV_EXCL_LINE
11547 return false; // LCOV_EXCL_LINE
11548 }
11549 }
11550 
11551 /*!
11552 @param[in] len the length of the array
11553 @return whether array creation completed
11554 */
11555 bool get_msgpack_array(const std::size_t len)
11556 {
11557 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11558 {
11559 return false;
11560 }
11561 
11562 for (std::size_t i = 0; i < len; ++i)
11563 {
11564 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11565 {
11566 return false;
11567 }
11568 }
11569 
11570 return sax->end_array();
11571 }
11572 
11573 /*!
11574 @param[in] len the length of the object
11575 @return whether object creation completed
11576 */
11577 bool get_msgpack_object(const std::size_t len)
11578 {
11579 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11580 {
11581 return false;
11582 }
11583 
11584 string_t key;
11585 for (std::size_t i = 0; i < len; ++i)
11586 {
11587 get();
11588 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11589 {
11590 return false;
11591 }
11592 
11593 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11594 {
11595 return false;
11596 }
11597 key.clear();
11598 }
11599 
11600 return sax->end_object();
11601 }
11602 
11603 ////////////
11604 // UBJSON //
11605 ////////////
11606 
11607 /*!
11608 @param[in] get_char whether a new character should be retrieved from the
11609 input (true, default) or whether the last read
11610 character should be considered instead
11611 
11612 @return whether a valid UBJSON value was passed to the SAX parser
11613 */
11614 bool parse_ubjson_internal(const bool get_char = true)
11615 {
11616 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11617 }
11618 
11619 /*!
11620 @brief reads a UBJSON string
11621 
11622 This function is either called after reading the 'S' byte explicitly
11623 indicating a string, or in case of an object key where the 'S' byte can be
11624 left out.
11625 
11626 @param[out] result created string
11627 @param[in] get_char whether a new character should be retrieved from the
11628 input (true, default) or whether the last read
11629 character should be considered instead
11630 
11631 @return whether string creation completed
11632 */
11633 bool get_ubjson_string(string_t& result, const bool get_char = true)
11634 {
11635 if (get_char)
11636 {
11637 get(); // TODO(niels): may we ignore N here?
11638 }
11639 
11640 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11641 {
11642 return false;
11643 }
11644 
11645 switch (current)
11646 {
11647 case 'U':
11648 {
11649 std::uint8_t len{};
11650 return get_number(input_format, len) && get_string(input_format, len, result);
11651 }
11652 
11653 case 'i':
11654 {
11655 std::int8_t len{};
11656 return get_number(input_format, len) && get_string(input_format, len, result);
11657 }
11658 
11659 case 'I':
11660 {
11661 std::int16_t len{};
11662 return get_number(input_format, len) && get_string(input_format, len, result);
11663 }
11664 
11665 case 'l':
11666 {
11667 std::int32_t len{};
11668 return get_number(input_format, len) && get_string(input_format, len, result);
11669 }
11670 
11671 case 'L':
11672 {
11673 std::int64_t len{};
11674 return get_number(input_format, len) && get_string(input_format, len, result);
11675 }
11676 
11677 case 'u':
11678 {
11679 if (input_format != input_format_t::bjdata)
11680 {
11681 break;
11682 }
11683 std::uint16_t len{};
11684 return get_number(input_format, len) && get_string(input_format, len, result);
11685 }
11686 
11687 case 'm':
11688 {
11689 if (input_format != input_format_t::bjdata)
11690 {
11691 break;
11692 }
11693 std::uint32_t len{};
11694 return get_number(input_format, len) && get_string(input_format, len, result);
11695 }
11696 
11697 case 'M':
11698 {
11699 if (input_format != input_format_t::bjdata)
11700 {
11701 break;
11702 }
11703 std::uint64_t len{};
11704 return get_number(input_format, len) && get_string(input_format, len, result);
11705 }
11706 
11707 default:
11708 break;
11709 }
11710 auto last_token = get_token_string();
11711 std::string message;
11712 
11713 if (input_format != input_format_t::bjdata)
11714 {
11715 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11716 }
11717 else
11718 {
11719 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11720 }
11721 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11722 }
11723 
11724 /*!
11725 @param[out] dim an integer vector storing the ND array dimensions
11726 @return whether reading ND array size vector is successful
11727 */
11728 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11729 {
11730 std::pair<std::size_t, char_int_type> size_and_type;
11731 size_t dimlen = 0;
11732 bool no_ndarray = true;
11733 
11734 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11735 {
11736 return false;
11737 }
11738 
11739 if (size_and_type.first != npos)
11740 {
11741 if (size_and_type.second != 0)
11742 {
11743 if (size_and_type.second != 'N')
11744 {
11745 for (std::size_t i = 0; i < size_and_type.first; ++i)
11746 {
11747 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11748 {
11749 return false;
11750 }
11751 dim.push_back(dimlen);
11752 }
11753 }
11754 }
11755 else
11756 {
11757 for (std::size_t i = 0; i < size_and_type.first; ++i)
11758 {
11759 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11760 {
11761 return false;
11762 }
11763 dim.push_back(dimlen);
11764 }
11765 }
11766 }
11767 else
11768 {
11769 while (current != ']')
11770 {
11771 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11772 {
11773 return false;
11774 }
11775 dim.push_back(dimlen);
11776 get_ignore_noop();
11777 }
11778 }
11779 return true;
11780 }
11781 
11782 /*!
11783 @param[out] result determined size
11784 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector
11785 or ndarray dimension is not allowed; `false` means ndarray
11786 is allowed; for output, `true` means an ndarray is found;
11787 is_ndarray can only return `true` when its initial value
11788 is `false`
11789 @param[in] prefix type marker if already read, otherwise set to 0
11790 
11791 @return whether size determination completed
11792 */
11793 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11794 {
11795 if (prefix == 0)
11796 {
11797 prefix = get_ignore_noop();
11798 }
11799 
11800 switch (prefix)
11801 {
11802 case 'U':
11803 {
11804 std::uint8_t number{};
11805 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11806 {
11807 return false;
11808 }
11809 result = static_cast<std::size_t>(number);
11810 return true;
11811 }
11812 
11813 case 'i':
11814 {
11815 std::int8_t number{};
11816 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11817 {
11818 return false;
11819 }
11820 if (number < 0)
11821 {
11822 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11823 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11824 }
11825 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11826 return true;
11827 }
11828 
11829 case 'I':
11830 {
11831 std::int16_t number{};
11832 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11833 {
11834 return false;
11835 }
11836 if (number < 0)
11837 {
11838 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11839 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11840 }
11841 result = static_cast<std::size_t>(number);
11842 return true;
11843 }
11844 
11845 case 'l':
11846 {
11847 std::int32_t number{};
11848 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11849 {
11850 return false;
11851 }
11852 if (number < 0)
11853 {
11854 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11855 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11856 }
11857 result = static_cast<std::size_t>(number);
11858 return true;
11859 }
11860 
11861 case 'L':
11862 {
11863 std::int64_t number{};
11864 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11865 {
11866 return false;
11867 }
11868 if (number < 0)
11869 {
11870 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11871 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11872 }
11873 if (!value_in_range_of<std::size_t>(number))
11874 {
11875 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11876 exception_message(input_format, "integer value overflow", "size"), nullptr));
11877 }
11878 result = static_cast<std::size_t>(number);
11879 return true;
11880 }
11881 
11882 case 'u':
11883 {
11884 if (input_format != input_format_t::bjdata)
11885 {
11886 break;
11887 }
11888 std::uint16_t number{};
11889 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11890 {
11891 return false;
11892 }
11893 result = static_cast<std::size_t>(number);
11894 return true;
11895 }
11896 
11897 case 'm':
11898 {
11899 if (input_format != input_format_t::bjdata)
11900 {
11901 break;
11902 }
11903 std::uint32_t number{};
11904 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11905 {
11906 return false;
11907 }
11908 result = conditional_static_cast<std::size_t>(number);
11909 return true;
11910 }
11911 
11912 case 'M':
11913 {
11914 if (input_format != input_format_t::bjdata)
11915 {
11916 break;
11917 }
11918 std::uint64_t number{};
11919 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11920 {
11921 return false;
11922 }
11923 if (!value_in_range_of<std::size_t>(number))
11924 {
11925 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11926 exception_message(input_format, "integer value overflow", "size"), nullptr));
11927 }
11928 result = detail::conditional_static_cast<std::size_t>(number);
11929 return true;
11930 }
11931 
11932 case '[':
11933 {
11934 if (input_format != input_format_t::bjdata)
11935 {
11936 break;
11937 }
11938 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11939 {
11940 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));
11941 }
11942 std::vector<size_t> dim;
11943 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11944 {
11945 return false;
11946 }
11947 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11948 {
11949 result = dim.at(dim.size() - 1);
11950 return true;
11951 }
11952 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11953 {
11954 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11955 {
11956 if ( i == 0 )
11957 {
11958 result = 0;
11959 return true;
11960 }
11961 }
11962 
11963 string_t key = "_ArraySize_";
11964 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11965 {
11966 return false;
11967 }
11968 result = 1;
11969 for (auto i : dim)
11970 {
11971 result *= i;
11972 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()
11973 {
11974 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));
11975 }
11976 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11977 {
11978 return false;
11979 }
11980 }
11981 is_ndarray = true;
11982 return sax->end_array();
11983 }
11984 result = 0;
11985 return true;
11986 }
11987 
11988 default:
11989 break;
11990 }
11991 auto last_token = get_token_string();
11992 std::string message;
11993 
11994 if (input_format != input_format_t::bjdata)
11995 {
11996 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11997 }
11998 else
11999 {
12000 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12001 }
12002 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12003 }
12004 
12005 /*!
12006 @brief determine the type and size for a container
12007 
12008 In the optimized UBJSON format, a type and a size can be provided to allow
12009 for a more compact representation.
12010 
12011 @param[out] result pair of the size and the type
12012 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector
12013 
12014 @return whether pair creation completed
12015 */
12016 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12017 {
12018 result.first = npos; // size
12019 result.second = 0; // type
12020 bool is_ndarray = false;
12021 
12022 get_ignore_noop();
12023 
12024 if (current == '$')
12025 {
12026 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12027 if (input_format == input_format_t::bjdata
12028 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12029 {
12030 auto last_token = get_token_string();
12031 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12032 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12033 }
12034 
12035 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12036 {
12037 return false;
12038 }
12039 
12040 get_ignore_noop();
12041 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12042 {
12043 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12044 {
12045 return false;
12046 }
12047 auto last_token = get_token_string();
12048 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12049 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12050 }
12051 
12052 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12053 if (input_format == input_format_t::bjdata && is_ndarray)
12054 {
12055 if (inside_ndarray)
12056 {
12057 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12058 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12059 }
12060 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12061 }
12062 return is_error;
12063 }
12064 
12065 if (current == '#')
12066 {
12067 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12068 if (input_format == input_format_t::bjdata && is_ndarray)
12069 {
12070 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12071 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12072 }
12073 return is_error;
12074 }
12075 
12076 return true;
12077 }
12078 
12079 /*!
12080 @param prefix the previously read or set type prefix
12081 @return whether value creation completed
12082 */
12083 bool get_ubjson_value(const char_int_type prefix)
12084 {
12085 switch (prefix)
12086 {
12087 case char_traits<char_type>::eof(): // EOF
12088 return unexpect_eof(input_format, "value");
12089 
12090 case 'T': // true
12091 return sax->boolean(true);
12092 case 'F': // false
12093 return sax->boolean(false);
12094 
12095 case 'Z': // null
12096 return sax->null();
12097 
12098 case 'B': // byte
12099 {
12100 if (input_format != input_format_t::bjdata)
12101 {
12102 break;
12103 }
12104 std::uint8_t number{};
12105 return get_number(input_format, number) && sax->number_unsigned(number);
12106 }
12107 
12108 case 'U':
12109 {
12110 std::uint8_t number{};
12111 return get_number(input_format, number) && sax->number_unsigned(number);
12112 }
12113 
12114 case 'i':
12115 {
12116 std::int8_t number{};
12117 return get_number(input_format, number) && sax->number_integer(number);
12118 }
12119 
12120 case 'I':
12121 {
12122 std::int16_t number{};
12123 return get_number(input_format, number) && sax->number_integer(number);
12124 }
12125 
12126 case 'l':
12127 {
12128 std::int32_t number{};
12129 return get_number(input_format, number) && sax->number_integer(number);
12130 }
12131 
12132 case 'L':
12133 {
12134 std::int64_t number{};
12135 return get_number(input_format, number) && sax->number_integer(number);
12136 }
12137 
12138 case 'u':
12139 {
12140 if (input_format != input_format_t::bjdata)
12141 {
12142 break;
12143 }
12144 std::uint16_t number{};
12145 return get_number(input_format, number) && sax->number_unsigned(number);
12146 }
12147 
12148 case 'm':
12149 {
12150 if (input_format != input_format_t::bjdata)
12151 {
12152 break;
12153 }
12154 std::uint32_t number{};
12155 return get_number(input_format, number) && sax->number_unsigned(number);
12156 }
12157 
12158 case 'M':
12159 {
12160 if (input_format != input_format_t::bjdata)
12161 {
12162 break;
12163 }
12164 std::uint64_t number{};
12165 return get_number(input_format, number) && sax->number_unsigned(number);
12166 }
12167 
12168 case 'h':
12169 {
12170 if (input_format != input_format_t::bjdata)
12171 {
12172 break;
12173 }
12174 const auto byte1_raw = get();
12175 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12176 {
12177 return false;
12178 }
12179 const auto byte2_raw = get();
12180 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12181 {
12182 return false;
12183 }
12184 
12185 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12186 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12187 
12188 // code from RFC 7049, Appendix D, Figure 3:
12189 // As half-precision floating-point numbers were only added
12190 // to IEEE 754 in 2008, today's programming platforms often
12191 // still only have limited support for them. It is very
12192 // easy to include at least decoding support for them even
12193 // without such support. An example of a small decoder for
12194 // half-precision floating-point numbers in the C language
12195 // is shown in Fig. 3.
12196 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12197 const double val = [&half]
12198 {
12199 const int exp = (half >> 10u) & 0x1Fu;
12200 const unsigned int mant = half & 0x3FFu;
12201 JSON_ASSERT(0 <= exp&& exp <= 32);
12202 JSON_ASSERT(mant <= 1024);
12203 switch (exp)
12204 {
12205 case 0:
12206 return std::ldexp(mant, -24);
12207 case 31:
12208 return (mant == 0)
12209 ? std::numeric_limits<double>::infinity()
12210 : std::numeric_limits<double>::quiet_NaN();
12211 default:
12212 return std::ldexp(mant + 1024, exp - 25);
12213 }
12214 }();
12215 return sax->number_float((half & 0x8000u) != 0
12216 ? static_cast<number_float_t>(-val)
12217 : static_cast<number_float_t>(val), "");
12218 }
12219 
12220 case 'd':
12221 {
12222 float number{};
12223 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12224 }
12225 
12226 case 'D':
12227 {
12228 double number{};
12229 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12230 }
12231 
12232 case 'H':
12233 {
12234 return get_ubjson_high_precision_number();
12235 }
12236 
12237 case 'C': // char
12238 {
12239 get();
12240 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12241 {
12242 return false;
12243 }
12244 if (JSON_HEDLEY_UNLIKELY(current > 127))
12245 {
12246 auto last_token = get_token_string();
12247 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12248 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12249 }
12250 string_t s(1, static_cast<typename string_t::value_type>(current));
12251 return sax->string(s);
12252 }
12253 
12254 case 'S': // string
12255 {
12256 string_t s;
12257 return get_ubjson_string(s) && sax->string(s);
12258 }
12259 
12260 case '[': // array
12261 return get_ubjson_array();
12262 
12263 case '{': // object
12264 return get_ubjson_object();
12265 
12266 default: // anything else
12267 break;
12268 }
12269 auto last_token = get_token_string();
12270 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));
12271 }
12272 
12273 /*!
12274 @return whether array creation completed
12275 */
12276 bool get_ubjson_array()
12277 {
12278 std::pair<std::size_t, char_int_type> size_and_type;
12279 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12280 {
12281 return false;
12282 }
12283 
12284 // 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):
12285 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12286 
12287 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12288 {
12289 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
12290 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)
12291 {
12292 return p.first < t;
12293 });
12294 string_t key = "_ArrayType_";
12295 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12296 {
12297 auto last_token = get_token_string();
12298 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12299 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12300 }
12301 
12302 string_t type = it->second; // sax->string() takes a reference
12303 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12304 {
12305 return false;
12306 }
12307 
12308 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12309 {
12310 size_and_type.second = 'U';
12311 }
12312 
12313 key = "_ArrayData_";
12314 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12315 {
12316 return false;
12317 }
12318 
12319 for (std::size_t i = 0; i < size_and_type.first; ++i)
12320 {
12321 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12322 {
12323 return false;
12324 }
12325 }
12326 
12327 return (sax->end_array() && sax->end_object());
12328 }
12329 
12330 // If BJData type marker is 'B' decode as binary
12331 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12332 {
12333 binary_t result;
12334 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12335 }
12336 
12337 if (size_and_type.first != npos)
12338 {
12339 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12340 {
12341 return false;
12342 }
12343 
12344 if (size_and_type.second != 0)
12345 {
12346 if (size_and_type.second != 'N')
12347 {
12348 for (std::size_t i = 0; i < size_and_type.first; ++i)
12349 {
12350 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12351 {
12352 return false;
12353 }
12354 }
12355 }
12356 }
12357 else
12358 {
12359 for (std::size_t i = 0; i < size_and_type.first; ++i)
12360 {
12361 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12362 {
12363 return false;
12364 }
12365 }
12366 }
12367 }
12368 else
12369 {
12370 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12371 {
12372 return false;
12373 }
12374 
12375 while (current != ']')
12376 {
12377 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12378 {
12379 return false;
12380 }
12381 get_ignore_noop();
12382 }
12383 }
12384 
12385 return sax->end_array();
12386 }
12387 
12388 /*!
12389 @return whether object creation completed
12390 */
12391 bool get_ubjson_object()
12392 {
12393 std::pair<std::size_t, char_int_type> size_and_type;
12394 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12395 {
12396 return false;
12397 }
12398 
12399 // do not accept ND-array size in objects in BJData
12400 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12401 {
12402 auto last_token = get_token_string();
12403 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12404 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12405 }
12406 
12407 string_t key;
12408 if (size_and_type.first != npos)
12409 {
12410 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12411 {
12412 return false;
12413 }
12414 
12415 if (size_and_type.second != 0)
12416 {
12417 for (std::size_t i = 0; i < size_and_type.first; ++i)
12418 {
12419 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12420 {
12421 return false;
12422 }
12423 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12424 {
12425 return false;
12426 }
12427 key.clear();
12428 }
12429 }
12430 else
12431 {
12432 for (std::size_t i = 0; i < size_and_type.first; ++i)
12433 {
12434 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12435 {
12436 return false;
12437 }
12438 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12439 {
12440 return false;
12441 }
12442 key.clear();
12443 }
12444 }
12445 }
12446 else
12447 {
12448 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12449 {
12450 return false;
12451 }
12452 
12453 while (current != '}')
12454 {
12455 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12456 {
12457 return false;
12458 }
12459 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12460 {
12461 return false;
12462 }
12463 get_ignore_noop();
12464 key.clear();
12465 }
12466 }
12467 
12468 return sax->end_object();
12469 }
12470 
12471 // Note, no reader for UBJSON binary types is implemented because they do
12472 // not exist
12473 
12474 bool get_ubjson_high_precision_number()
12475 {
12476 // get size of following number string
12477 std::size_t size{};
12478 bool no_ndarray = true;
12479 auto res = get_ubjson_size_value(size, no_ndarray);
12480 if (JSON_HEDLEY_UNLIKELY(!res))
12481 {
12482 return res;
12483 }
12484 
12485 // get number string
12486 std::vector<char> number_vector;
12487 for (std::size_t i = 0; i < size; ++i)
12488 {
12489 get();
12490 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12491 {
12492 return false;
12493 }
12494 number_vector.push_back(static_cast<char>(current));
12495 }
12496 
12497 // parse number string
12498 using ia_type = decltype(detail::input_adapter(number_vector));
12499 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12500 const auto result_number = number_lexer.scan();
12501 const auto number_string = number_lexer.get_token_string();
12502 const auto result_remainder = number_lexer.scan();
12503 
12504 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12505 
12506 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12507 {
12508 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12509 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12510 }
12511 
12512 switch (result_number)
12513 {
12514 case token_type::value_integer:
12515 return sax->number_integer(number_lexer.get_number_integer());
12516 case token_type::value_unsigned:
12517 return sax->number_unsigned(number_lexer.get_number_unsigned());
12518 case token_type::value_float:
12519 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12520 case token_type::uninitialized:
12521 case token_type::literal_true:
12522 case token_type::literal_false:
12523 case token_type::literal_null:
12524 case token_type::value_string:
12525 case token_type::begin_array:
12526 case token_type::begin_object:
12527 case token_type::end_array:
12528 case token_type::end_object:
12529 case token_type::name_separator:
12530 case token_type::value_separator:
12531 case token_type::parse_error:
12532 case token_type::end_of_input:
12533 case token_type::literal_or_value:
12534 default:
12535 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12536 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12537 }
12538 }
12539 
12540 ///////////////////////
12541 // Utility functions //
12542 ///////////////////////
12543 
12544 /*!
12545 @brief get next character from the input
12546 
12547 This function provides the interface to the used input adapter. It does
12548 not throw in case the input reached EOF, but returns a -'ve valued
12549 `char_traits<char_type>::eof()` in that case.
12550 
12551 @return character read from the input
12552 */
12553 char_int_type get()
12554 {
12555 ++chars_read;
12556 return current = ia.get_character();
12557 }
12558 
12559 /*!
12560 @brief get_to read into a primitive type
12561 
12562 This function provides the interface to the used input adapter. It does
12563 not throw in case the input reached EOF, but returns false instead
12564 
12565 @return bool, whether the read was successful
12566 */
12567 template<class T>
12568 bool get_to(T& dest, const input_format_t format, const char* context)
12569 {
12570 auto new_chars_read = ia.get_elements(&dest);
12571 chars_read += new_chars_read;
12572 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12573 {
12574 // in case of failure, advance position by 1 to report failing location
12575 ++chars_read;
12576 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12577 return false;
12578 }
12579 return true;
12580 }
12581 
12582 /*!
12583 @return character read from the input after ignoring all 'N' entries
12584 */
12585 char_int_type get_ignore_noop()
12586 {
12587 do
12588 {
12589 get();
12590 }
12591 while (current == 'N');
12592 
12593 return current;
12594 }
12595 
12596 template<class NumberType>
12597 static void byte_swap(NumberType& number)
12598 {
12599 constexpr std::size_t sz = sizeof(number);
12600#ifdef __cpp_lib_byteswap
12601 if constexpr (sz == 1)
12602 {
12603 return;
12604 }
12605 if constexpr(std::is_integral_v<NumberType>)
12606 {
12607 number = std::byteswap(number);
12608 return;
12609 }
12610#endif
12611 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12612 for (std::size_t i = 0; i < sz / 2; ++i)
12613 {
12614 std::swap(ptr[i], ptr[sz - i - 1]);
12615 }
12616 }
12617 
12618 /*
12619 @brief read a number from the input
12620 
12621 @tparam NumberType the type of the number
12622 @param[in] format the current format (for diagnostics)
12623 @param[out] result number of type @a NumberType
12624 
12625 @return whether conversion completed
12626 
12627 @note This function needs to respect the system's endianness, because
12628 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12629 (big endian) and therefore need reordering on little endian systems.
12630 On the other hand, BSON and BJData use little endian and should reorder
12631 on big endian systems.
12632 */
12633 template<typename NumberType, bool InputIsLittleEndian = false>
12634 bool get_number(const input_format_t format, NumberType& result)
12635 {
12636 // read in the original format
12637 
12638 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12639 {
12640 return false;
12641 }
12642 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12643 {
12644 byte_swap(result);
12645 }
12646 return true;
12647 }
12648 
12649 /*!
12650 @brief create a string by reading characters from the input
12651 
12652 @tparam NumberType the type of the number
12653 @param[in] format the current format (for diagnostics)
12654 @param[in] len number of characters to read
12655 @param[out] result string created by reading @a len bytes
12656 
12657 @return whether string creation completed
12658 
12659 @note We can not reserve @a len bytes for the result, because @a len
12660 may be too large. Usually, @ref unexpect_eof() detects the end of
12661 the input before we run out of string memory.
12662 */
12663 template<typename NumberType>
12664 bool get_string(const input_format_t format,
12665 const NumberType len,
12666 string_t& result)
12667 {
12668 bool success = true;
12669 for (NumberType i = 0; i < len; i++)
12670 {
12671 get();
12672 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12673 {
12674 success = false;
12675 break;
12676 }
12677 result.push_back(static_cast<typename string_t::value_type>(current));
12678 }
12679 return success;
12680 }
12681 
12682 /*!
12683 @brief create a byte array by reading bytes from the input
12684 
12685 @tparam NumberType the type of the number
12686 @param[in] format the current format (for diagnostics)
12687 @param[in] len number of bytes to read
12688 @param[out] result byte array created by reading @a len bytes
12689 
12690 @return whether byte array creation completed
12691 
12692 @note We can not reserve @a len bytes for the result, because @a len
12693 may be too large. Usually, @ref unexpect_eof() detects the end of
12694 the input before we run out of memory.
12695 */
12696 template<typename NumberType>
12697 bool get_binary(const input_format_t format,
12698 const NumberType len,
12699 binary_t& result)
12700 {
12701 bool success = true;
12702 for (NumberType i = 0; i < len; i++)
12703 {
12704 get();
12705 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12706 {
12707 success = false;
12708 break;
12709 }
12710 result.push_back(static_cast<std::uint8_t>(current));
12711 }
12712 return success;
12713 }
12714 
12715 /*!
12716 @param[in] format the current format (for diagnostics)
12717 @param[in] context further context information (for diagnostics)
12718 @return whether the last read character is not EOF
12719 */
12720 JSON_HEDLEY_NON_NULL(3)
12721 bool unexpect_eof(const input_format_t format, const char* context) const
12722 {
12723 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12724 {
12725 return sax->parse_error(chars_read, "<end of file>",
12726 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12727 }
12728 return true;
12729 }
12730 
12731 /*!
12732 @return a string representation of the last read byte
12733 */
12734 std::string get_token_string() const
12735 {
12736 std::array<char, 3> cr{{}};
12737 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12738 return std::string{cr.data()};
12739 }
12740 
12741 /*!
12742 @param[in] format the current format
12743 @param[in] detail a detailed error message
12744 @param[in] context further context information
12745 @return a message string to use in the parse_error exceptions
12746 */
12747 std::string exception_message(const input_format_t format,
12748 const std::string& detail,
12749 const std::string& context) const
12750 {
12751 std::string error_msg = "syntax error while parsing ";
12752 
12753 switch (format)
12754 {
12755 case input_format_t::cbor:
12756 error_msg += "CBOR";
12757 break;
12758 
12759 case input_format_t::msgpack:
12760 error_msg += "MessagePack";
12761 break;
12762 
12763 case input_format_t::ubjson:
12764 error_msg += "UBJSON";
12765 break;
12766 
12767 case input_format_t::bson:
12768 error_msg += "BSON";
12769 break;
12770 
12771 case input_format_t::bjdata:
12772 error_msg += "BJData";
12773 break;
12774 
12775 case input_format_t::json: // LCOV_EXCL_LINE
12776 default: // LCOV_EXCL_LINE
12777 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12778 }
12779 
12780 return concat(error_msg, ' ', context, ": ", detail);
12781 }
12782 
12783 private:
12784 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12785 
12786 /// input adapter
12787 InputAdapterType ia;
12788 
12789 /// the current character
12790 char_int_type current = char_traits<char_type>::eof();
12791 
12792 /// the number of characters read
12793 std::size_t chars_read = 0;
12794 
12795 /// whether we can assume little endianness
12796 const bool is_little_endian = little_endianness();
12797 
12798 /// input format
12799 const input_format_t input_format = input_format_t::json;
12800 
12801 /// the SAX parser
12802 json_sax_t* sax = nullptr;
12803 
12804 // excluded markers in bjdata optimized type
12805#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12806 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12807 
12808#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12809 make_array<bjd_type>( \
12810 bjd_type{'B', "byte"}, \
12811 bjd_type{'C', "char"}, \
12812 bjd_type{'D', "double"}, \
12813 bjd_type{'I', "int16"}, \
12814 bjd_type{'L', "int64"}, \
12815 bjd_type{'M', "uint64"}, \
12816 bjd_type{'U', "uint8"}, \
12817 bjd_type{'d', "single"}, \
12818 bjd_type{'i', "int8"}, \
12819 bjd_type{'l', "int32"}, \
12820 bjd_type{'m', "uint32"}, \
12821 bjd_type{'u', "uint16"})
12822 
12823 JSON_PRIVATE_UNLESS_TESTED:
12824 // lookup tables
12825 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12826 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12827 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12828 
12829 using bjd_type = std::pair<char_int_type, string_t>;
12830 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12831 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12832 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12833 
12834#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12835#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12836};
12837 
12838#ifndef JSON_HAS_CPP_17
12839 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12840 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12841#endif
12842 
12843} // namespace detail
12844NLOHMANN_JSON_NAMESPACE_END
12845 
12846// #include <nlohmann/detail/input/input_adapters.hpp>
12847 
12848// #include <nlohmann/detail/input/lexer.hpp>
12849 
12850// #include <nlohmann/detail/input/parser.hpp>
12851// __ _____ _____ _____
12852// __| | __| | | | JSON for Modern C++
12853// | | |__ | | | | | | version 3.12.0
12854// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12855//
12856// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12857// SPDX-License-Identifier: MIT
12858 
12859 
12860 
12861#include <cmath> // isfinite
12862#include <cstdint> // uint8_t
12863#include <functional> // function
12864#include <string> // string
12865#include <utility> // move
12866#include <vector> // vector
12867 
12868// #include <nlohmann/detail/exceptions.hpp>
12869 
12870// #include <nlohmann/detail/input/input_adapters.hpp>
12871 
12872// #include <nlohmann/detail/input/json_sax.hpp>
12873 
12874// #include <nlohmann/detail/input/lexer.hpp>
12875 
12876// #include <nlohmann/detail/macro_scope.hpp>
12877 
12878// #include <nlohmann/detail/meta/is_sax.hpp>
12879 
12880// #include <nlohmann/detail/string_concat.hpp>
12881 
12882// #include <nlohmann/detail/value_t.hpp>
12883 
12884 
12885NLOHMANN_JSON_NAMESPACE_BEGIN
12886namespace detail
12887{
12888////////////
12889// parser //
12890////////////
12891 
12892enum class parse_event_t : std::uint8_t
12893{
12894 /// the parser read `{` and started to process a JSON object
12895 object_start,
12896 /// the parser read `}` and finished processing a JSON object
12897 object_end,
12898 /// the parser read `[` and started to process a JSON array
12899 array_start,
12900 /// the parser read `]` and finished processing a JSON array
12901 array_end,
12902 /// the parser read a key of a value in an object
12903 key,
12904 /// the parser finished reading a JSON value
12905 value
12906};
12907 
12908template<typename BasicJsonType>
12909using parser_callback_t =
12910 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12911 
12912/*!
12913@brief syntax analysis
12914 
12915This class implements a recursive descent parser.
12916*/
12917template<typename BasicJsonType, typename InputAdapterType>
12918class parser
12919{
12920 using number_integer_t = typename BasicJsonType::number_integer_t;
12921 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12922 using number_float_t = typename BasicJsonType::number_float_t;
12923 using string_t = typename BasicJsonType::string_t;
12924 using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12925 using token_type = typename lexer_t::token_type;
12926 
12927 public:
12928 /// a parser reading from an input adapter
12929 explicit parser(InputAdapterType&& adapter,
12930 parser_callback_t<BasicJsonType> cb = nullptr,
12931 const bool allow_exceptions_ = true,
12932 const bool skip_comments = false)
12933 : callback(std::move(cb))
12934 , m_lexer(std::move(adapter), skip_comments)
12935 , allow_exceptions(allow_exceptions_)
12936 {
12937 // read first token
12938 get_token();
12939 }
12940 
12941 /*!
12942 @brief public parser interface
12943 
12944 @param[in] strict whether to expect the last token to be EOF
12945 @param[in,out] result parsed JSON value
12946 
12947 @throw parse_error.101 in case of an unexpected token
12948 @throw parse_error.102 if to_unicode fails or surrogate error
12949 @throw parse_error.103 if to_unicode fails
12950 */
12951 void parse(const bool strict, BasicJsonType& result)
12952 {
12953 if (callback)
12954 {
12955 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
12956 sax_parse_internal(&sdp);
12957 
12958 // in strict mode, input must be completely read
12959 if (strict && (get_token() != token_type::end_of_input))
12960 {
12961 sdp.parse_error(m_lexer.get_position(),
12962 m_lexer.get_token_string(),
12963 parse_error::create(101, m_lexer.get_position(),
12964 exception_message(token_type::end_of_input, "value"), nullptr));
12965 }
12966 
12967 // in case of an error, return discarded value
12968 if (sdp.is_errored())
12969 {
12970 result = value_t::discarded;
12971 return;
12972 }
12973 
12974 // set top-level value to null if it was discarded by the callback
12975 // function
12976 if (result.is_discarded())
12977 {
12978 result = nullptr;
12979 }
12980 }
12981 else
12982 {
12983 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
12984 sax_parse_internal(&sdp);
12985 
12986 // in strict mode, input must be completely read
12987 if (strict && (get_token() != token_type::end_of_input))
12988 {
12989 sdp.parse_error(m_lexer.get_position(),
12990 m_lexer.get_token_string(),
12991 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12992 }
12993 
12994 // in case of an error, return discarded value
12995 if (sdp.is_errored())
12996 {
12997 result = value_t::discarded;
12998 return;
12999 }
13000 }
13001 
13002 result.assert_invariant();
13003 }
13004 
13005 /*!
13006 @brief public accept interface
13007 
13008 @param[in] strict whether to expect the last token to be EOF
13009 @return whether the input is a proper JSON text
13010 */
13011 bool accept(const bool strict = true)
13012 {
13013 json_sax_acceptor<BasicJsonType> sax_acceptor;
13014 return sax_parse(&sax_acceptor, strict);
13015 }
13016 
13017 template<typename SAX>
13018 JSON_HEDLEY_NON_NULL(2)
13019 bool sax_parse(SAX* sax, const bool strict = true)
13020 {
13021 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
13022 const bool result = sax_parse_internal(sax);
13023 
13024 // strict mode: next byte must be EOF
13025 if (result && strict && (get_token() != token_type::end_of_input))
13026 {
13027 return sax->parse_error(m_lexer.get_position(),
13028 m_lexer.get_token_string(),
13029 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13030 }
13031 
13032 return result;
13033 }
13034 
13035 private:
13036 template<typename SAX>
13037 JSON_HEDLEY_NON_NULL(2)
13038 bool sax_parse_internal(SAX* sax)
13039 {
13040 // stack to remember the hierarchy of structured values we are parsing
13041 // true = array; false = object
13042 std::vector<bool> states;
13043 // value to avoid a goto (see comment where set to true)
13044 bool skip_to_state_evaluation = false;
13045 
13046 while (true)
13047 {
13048 if (!skip_to_state_evaluation)
13049 {
13050 // invariant: get_token() was called before each iteration
13051 switch (last_token)
13052 {
13053 case token_type::begin_object:
13054 {
13055 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13056 {
13057 return false;
13058 }
13059 
13060 // closing } -> we are done
13061 if (get_token() == token_type::end_object)
13062 {
13063 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13064 {
13065 return false;
13066 }
13067 break;
13068 }
13069 
13070 // parse key
13071 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13072 {
13073 return sax->parse_error(m_lexer.get_position(),
13074 m_lexer.get_token_string(),
13075 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13076 }
13077 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13078 {
13079 return false;
13080 }
13081 
13082 // parse separator (:)
13083 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13084 {
13085 return sax->parse_error(m_lexer.get_position(),
13086 m_lexer.get_token_string(),
13087 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13088 }
13089 
13090 // remember we are now inside an object
13091 states.push_back(false);
13092 
13093 // parse values
13094 get_token();
13095 continue;
13096 }
13097 
13098 case token_type::begin_array:
13099 {
13100 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13101 {
13102 return false;
13103 }
13104 
13105 // closing ] -> we are done
13106 if (get_token() == token_type::end_array)
13107 {
13108 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13109 {
13110 return false;
13111 }
13112 break;
13113 }
13114 
13115 // remember we are now inside an array
13116 states.push_back(true);
13117 
13118 // parse values (no need to call get_token)
13119 continue;
13120 }
13121 
13122 case token_type::value_float:
13123 {
13124 const auto res = m_lexer.get_number_float();
13125 
13126 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13127 {
13128 return sax->parse_error(m_lexer.get_position(),
13129 m_lexer.get_token_string(),
13130 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13131 }
13132 
13133 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13134 {
13135 return false;
13136 }
13137 
13138 break;
13139 }
13140 
13141 case token_type::literal_false:
13142 {
13143 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13144 {
13145 return false;
13146 }
13147 break;
13148 }
13149 
13150 case token_type::literal_null:
13151 {
13152 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13153 {
13154 return false;
13155 }
13156 break;
13157 }
13158 
13159 case token_type::literal_true:
13160 {
13161 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13162 {
13163 return false;
13164 }
13165 break;
13166 }
13167 
13168 case token_type::value_integer:
13169 {
13170 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13171 {
13172 return false;
13173 }
13174 break;
13175 }
13176 
13177 case token_type::value_string:
13178 {
13179 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13180 {
13181 return false;
13182 }
13183 break;
13184 }
13185 
13186 case token_type::value_unsigned:
13187 {
13188 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13189 {
13190 return false;
13191 }
13192 break;
13193 }
13194 
13195 case token_type::parse_error:
13196 {
13197 // using "uninitialized" to avoid "expected" message
13198 return sax->parse_error(m_lexer.get_position(),
13199 m_lexer.get_token_string(),
13200 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13201 }
13202 case token_type::end_of_input:
13203 {
13204 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13205 {
13206 return sax->parse_error(m_lexer.get_position(),
13207 m_lexer.get_token_string(),
13208 parse_error::create(101, m_lexer.get_position(),
13209 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13210 }
13211 
13212 return sax->parse_error(m_lexer.get_position(),
13213 m_lexer.get_token_string(),
13214 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13215 }
13216 case token_type::uninitialized:
13217 case token_type::end_array:
13218 case token_type::end_object:
13219 case token_type::name_separator:
13220 case token_type::value_separator:
13221 case token_type::literal_or_value:
13222 default: // the last token was unexpected
13223 {
13224 return sax->parse_error(m_lexer.get_position(),
13225 m_lexer.get_token_string(),
13226 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13227 }
13228 }
13229 }
13230 else
13231 {
13232 skip_to_state_evaluation = false;
13233 }
13234 
13235 // we reached this line after we successfully parsed a value
13236 if (states.empty())
13237 {
13238 // empty stack: we reached the end of the hierarchy: done
13239 return true;
13240 }
13241 
13242 if (states.back()) // array
13243 {
13244 // comma -> next value
13245 if (get_token() == token_type::value_separator)
13246 {
13247 // parse a new value
13248 get_token();
13249 continue;
13250 }
13251 
13252 // closing ]
13253 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13254 {
13255 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13256 {
13257 return false;
13258 }
13259 
13260 // We are done with this array. Before we can parse a
13261 // new value, we need to evaluate the new state first.
13262 // By setting skip_to_state_evaluation to false, we
13263 // are effectively jumping to the beginning of this if.
13264 JSON_ASSERT(!states.empty());
13265 states.pop_back();
13266 skip_to_state_evaluation = true;
13267 continue;
13268 }
13269 
13270 return sax->parse_error(m_lexer.get_position(),
13271 m_lexer.get_token_string(),
13272 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13273 }
13274 
13275 // states.back() is false -> object
13276 
13277 // comma -> next value
13278 if (get_token() == token_type::value_separator)
13279 {
13280 // parse key
13281 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
13282 {
13283 return sax->parse_error(m_lexer.get_position(),
13284 m_lexer.get_token_string(),
13285 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13286 }
13287 
13288 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13289 {
13290 return false;
13291 }
13292 
13293 // parse separator (:)
13294 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13295 {
13296 return sax->parse_error(m_lexer.get_position(),
13297 m_lexer.get_token_string(),
13298 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13299 }
13300 
13301 // parse values
13302 get_token();
13303 continue;
13304 }
13305 
13306 // closing }
13307 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13308 {
13309 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13310 {
13311 return false;
13312 }
13313 
13314 // We are done with this object. Before we can parse a
13315 // new value, we need to evaluate the new state first.
13316 // By setting skip_to_state_evaluation to false, we
13317 // are effectively jumping to the beginning of this if.
13318 JSON_ASSERT(!states.empty());
13319 states.pop_back();
13320 skip_to_state_evaluation = true;
13321 continue;
13322 }
13323 
13324 return sax->parse_error(m_lexer.get_position(),
13325 m_lexer.get_token_string(),
13326 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13327 }
13328 }
13329 
13330 /// get next token from lexer
13331 token_type get_token()
13332 {
13333 return last_token = m_lexer.scan();
13334 }
13335 
13336 std::string exception_message(const token_type expected, const std::string& context)
13337 {
13338 std::string error_msg = "syntax error ";
13339 
13340 if (!context.empty())
13341 {
13342 error_msg += concat("while parsing ", context, ' ');
13343 }
13344 
13345 error_msg += "- ";
13346 
13347 if (last_token == token_type::parse_error)
13348 {
13349 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13350 m_lexer.get_token_string(), '\'');
13351 }
13352 else
13353 {
13354 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13355 }
13356 
13357 if (expected != token_type::uninitialized)
13358 {
13359 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13360 }
13361 
13362 return error_msg;
13363 }
13364 
13365 private:
13366 /// callback function
13367 const parser_callback_t<BasicJsonType> callback = nullptr;
13368 /// the type of the last read token
13369 token_type last_token = token_type::uninitialized;
13370 /// the lexer
13371 lexer_t m_lexer;
13372 /// whether to throw exceptions in case of errors
13373 const bool allow_exceptions = true;
13374};
13375 
13376} // namespace detail
13377NLOHMANN_JSON_NAMESPACE_END
13378 
13379// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13380// __ _____ _____ _____
13381// __| | __| | | | JSON for Modern C++
13382// | | |__ | | | | | | version 3.12.0
13383// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13384//
13385// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13386// SPDX-License-Identifier: MIT
13387 
13388 
13389 
13390// #include <nlohmann/detail/abi_macros.hpp>
13391 
13392// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13393// __ _____ _____ _____
13394// __| | __| | | | JSON for Modern C++
13395// | | |__ | | | | | | version 3.12.0
13396// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13397//
13398// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13399// SPDX-License-Identifier: MIT
13400 
13401 
13402 
13403#include <cstddef> // ptrdiff_t
13404#include <limits> // numeric_limits
13405 
13406// #include <nlohmann/detail/macro_scope.hpp>
13407 
13408 
13409NLOHMANN_JSON_NAMESPACE_BEGIN
13410namespace detail
13411{
13412 
13413/*
13414@brief an iterator for primitive JSON types
13415 
13416This class models an iterator for primitive JSON types (boolean, number,
13417string). It's only purpose is to allow the iterator/const_iterator classes
13418to "iterate" over primitive values. Internally, the iterator is modeled by
13419a `difference_type` variable. Value begin_value (`0`) models the begin,
13420end_value (`1`) models past the end.
13421*/
13422class primitive_iterator_t
13423{
13424 private:
13425 using difference_type = std::ptrdiff_t;
13426 static constexpr difference_type begin_value = 0;
13427 static constexpr difference_type end_value = begin_value + 1;
13428 
13429 JSON_PRIVATE_UNLESS_TESTED:
13430 /// iterator as signed integer type
13431 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13432 
13433 public:
13434 constexpr difference_type get_value() const noexcept
13435 {
13436 return m_it;
13437 }
13438 
13439 /// set iterator to a defined beginning
13440 void set_begin() noexcept
13441 {
13442 m_it = begin_value;
13443 }
13444 
13445 /// set iterator to a defined past the end
13446 void set_end() noexcept
13447 {
13448 m_it = end_value;
13449 }
13450 
13451 /// return whether the iterator can be dereferenced
13452 constexpr bool is_begin() const noexcept
13453 {
13454 return m_it == begin_value;
13455 }
13456 
13457 /// return whether the iterator is at end
13458 constexpr bool is_end() const noexcept
13459 {
13460 return m_it == end_value;
13461 }
13462 
13463 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13464 {
13465 return lhs.m_it == rhs.m_it;
13466 }
13467 
13468 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13469 {
13470 return lhs.m_it < rhs.m_it;
13471 }
13472 
13473 primitive_iterator_t operator+(difference_type n) noexcept
13474 {
13475 auto result = *this;
13476 result += n;
13477 return result;
13478 }
13479 
13480 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13481 {
13482 return lhs.m_it - rhs.m_it;
13483 }
13484 
13485 primitive_iterator_t& operator++() noexcept
13486 {
13487 ++m_it;
13488 return *this;
13489 }
13490 
13491 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13492 {
13493 auto result = *this;
13494 ++m_it;
13495 return result;
13496 }
13497 
13498 primitive_iterator_t& operator--() noexcept
13499 {
13500 --m_it;
13501 return *this;
13502 }
13503 
13504 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13505 {
13506 auto result = *this;
13507 --m_it;
13508 return result;
13509 }
13510 
13511 primitive_iterator_t& operator+=(difference_type n) noexcept
13512 {
13513 m_it += n;
13514 return *this;
13515 }
13516 
13517 primitive_iterator_t& operator-=(difference_type n) noexcept
13518 {
13519 m_it -= n;
13520 return *this;
13521 }
13522};
13523 
13524} // namespace detail
13525NLOHMANN_JSON_NAMESPACE_END
13526 
13527 
13528NLOHMANN_JSON_NAMESPACE_BEGIN
13529namespace detail
13530{
13531 
13532/*!
13533@brief an iterator value
13534 
13535@note This structure could easily be a union, but MSVC currently does not allow
13536unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
13537*/
13538template<typename BasicJsonType> struct internal_iterator
13539{
13540 /// iterator for JSON objects
13541 typename BasicJsonType::object_t::iterator object_iterator {};
13542 /// iterator for JSON arrays
13543 typename BasicJsonType::array_t::iterator array_iterator {};
13544 /// generic iterator for all other types
13545 primitive_iterator_t primitive_iterator {};
13546};
13547 
13548} // namespace detail
13549NLOHMANN_JSON_NAMESPACE_END
13550 
13551// #include <nlohmann/detail/iterators/iter_impl.hpp>
13552// __ _____ _____ _____
13553// __| | __| | | | JSON for Modern C++
13554// | | |__ | | | | | | version 3.12.0
13555// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13556//
13557// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13558// SPDX-License-Identifier: MIT
13559 
13560 
13561 
13562#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13563#include <type_traits> // conditional, is_const, remove_const
13564 
13565// #include <nlohmann/detail/exceptions.hpp>
13566 
13567// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13568 
13569// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13570 
13571// #include <nlohmann/detail/macro_scope.hpp>
13572 
13573// #include <nlohmann/detail/meta/cpp_future.hpp>
13574 
13575// #include <nlohmann/detail/meta/type_traits.hpp>
13576 
13577// #include <nlohmann/detail/value_t.hpp>
13578 
13579 
13580NLOHMANN_JSON_NAMESPACE_BEGIN
13581namespace detail
13582{
13583 
13584// forward declare, to be able to friend it later on
13585template<typename IteratorType> class iteration_proxy;
13586template<typename IteratorType> class iteration_proxy_value;
13587 
13588/*!
13589@brief a template for a bidirectional iterator for the @ref basic_json class
13590This class implements a both iterators (iterator and const_iterator) for the
13591@ref basic_json class.
13592@note An iterator is called *initialized* when a pointer to a JSON value has
13593 been set (e.g., by a constructor or a copy assignment). If the iterator is
13594 default-constructed, it is *uninitialized* and most methods are undefined.
13595 **The library uses assertions to detect calls on uninitialized iterators.**
13596@requirement The class satisfies the following concept requirements:
13597-
13598[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13599 The iterator that can be moved can be moved in both directions (i.e.
13600 incremented and decremented).
13601@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
13602 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
13603*/
13604template<typename BasicJsonType>
13605class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13606{
13607 /// the iterator with BasicJsonType of different const-ness
13608 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13609 /// allow basic_json to access private members
13610 friend other_iter_impl;
13611 friend BasicJsonType;
13612 friend iteration_proxy<iter_impl>;
13613 friend iteration_proxy_value<iter_impl>;
13614 
13615 using object_t = typename BasicJsonType::object_t;
13616 using array_t = typename BasicJsonType::array_t;
13617 // make sure BasicJsonType is basic_json or const basic_json
13618 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
13619 "iter_impl only accepts (const) basic_json");
13620 // superficial check for the LegacyBidirectionalIterator named requirement
13621 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13622 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13623 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13624 
13625 public:
13626 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
13627 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
13628 /// A user-defined iterator should provide publicly accessible typedefs named
13629 /// iterator_category, value_type, difference_type, pointer, and reference.
13630 /// Note that value_type is required to be non-const, even for constant iterators.
13631 using iterator_category = std::bidirectional_iterator_tag;
13632 
13633 /// the type of the values when the iterator is dereferenced
13634 using value_type = typename BasicJsonType::value_type;
13635 /// a type to represent differences between iterators
13636 using difference_type = typename BasicJsonType::difference_type;
13637 /// defines a pointer to the type iterated over (value_type)
13638 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13639 typename BasicJsonType::const_pointer,
13640 typename BasicJsonType::pointer>::type;
13641 /// defines a reference to the type iterated over (value_type)
13642 using reference =
13643 typename std::conditional<std::is_const<BasicJsonType>::value,
13644 typename BasicJsonType::const_reference,
13645 typename BasicJsonType::reference>::type;
13646 
13647 iter_impl() = default;
13648 ~iter_impl() = default;
13649 iter_impl(iter_impl&&) noexcept = default;
13650 iter_impl& operator=(iter_impl&&) noexcept = default;
13651 
13652 /*!
13653 @brief constructor for a given JSON instance
13654 @param[in] object pointer to a JSON object for this iterator
13655 @pre object != nullptr
13656 @post The iterator is initialized; i.e. `m_object != nullptr`.
13657 */
13658 explicit iter_impl(pointer object) noexcept : m_object(object)
13659 {
13660 JSON_ASSERT(m_object != nullptr);
13661 
13662 switch (m_object->m_data.m_type)
13663 {
13664 case value_t::object:
13665 {
13666 m_it.object_iterator = typename object_t::iterator();
13667 break;
13668 }
13669 
13670 case value_t::array:
13671 {
13672 m_it.array_iterator = typename array_t::iterator();
13673 break;
13674 }
13675 
13676 case value_t::null:
13677 case value_t::string:
13678 case value_t::boolean:
13679 case value_t::number_integer:
13680 case value_t::number_unsigned:
13681 case value_t::number_float:
13682 case value_t::binary:
13683 case value_t::discarded:
13684 default:
13685 {
13686 m_it.primitive_iterator = primitive_iterator_t();
13687 break;
13688 }
13689 }
13690 }
13691 
13692 /*!
13693 @note The conventional copy constructor and copy assignment are implicitly
13694 defined. Combined with the following converting constructor and
13695 assignment, they support: (1) copy from iterator to iterator, (2)
13696 copy from const iterator to const iterator, and (3) conversion from
13697 iterator to const iterator. However conversion from const iterator
13698 to iterator is not defined.
13699 */
13700 
13701 /*!
13702 @brief const copy constructor
13703 @param[in] other const iterator to copy from
13704 @note This copy constructor had to be defined explicitly to circumvent a bug
13705 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
13706 information refer to: https://github.com/nlohmann/json/issues/1608
13707 */
13708 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13709 : m_object(other.m_object), m_it(other.m_it)
13710 {}
13711 
13712 /*!
13713 @brief converting assignment
13714 @param[in] other const iterator to copy from
13715 @return const/non-const iterator
13716 @note It is not checked whether @a other is initialized.
13717 */
13718 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
13719 {
13720 if (&other != this)
13721 {
13722 m_object = other.m_object;
13723 m_it = other.m_it;
13724 }
13725 return *this;
13726 }
13727 
13728 /*!
13729 @brief converting constructor
13730 @param[in] other non-const iterator to copy from
13731 @note It is not checked whether @a other is initialized.
13732 */
13733 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13734 : m_object(other.m_object), m_it(other.m_it)
13735 {}
13736 
13737 /*!
13738 @brief converting assignment
13739 @param[in] other non-const iterator to copy from
13740 @return const/non-const iterator
13741 @note It is not checked whether @a other is initialized.
13742 */
13743 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13744 {
13745 m_object = other.m_object;
13746 m_it = other.m_it;
13747 return *this;
13748 }
13749 
13750 JSON_PRIVATE_UNLESS_TESTED:
13751 /*!
13752 @brief set the iterator to the first value
13753 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13754 */
13755 void set_begin() noexcept
13756 {
13757 JSON_ASSERT(m_object != nullptr);
13758 
13759 switch (m_object->m_data.m_type)
13760 {
13761 case value_t::object:
13762 {
13763 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13764 break;
13765 }
13766 
13767 case value_t::array:
13768 {
13769 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13770 break;
13771 }
13772 
13773 case value_t::null:
13774 {
13775 // set to end so begin()==end() is true: null is empty
13776 m_it.primitive_iterator.set_end();
13777 break;
13778 }
13779 
13780 case value_t::string:
13781 case value_t::boolean:
13782 case value_t::number_integer:
13783 case value_t::number_unsigned:
13784 case value_t::number_float:
13785 case value_t::binary:
13786 case value_t::discarded:
13787 default:
13788 {
13789 m_it.primitive_iterator.set_begin();
13790 break;
13791 }
13792 }
13793 }
13794 
13795 /*!
13796 @brief set the iterator past the last value
13797 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13798 */
13799 void set_end() noexcept
13800 {
13801 JSON_ASSERT(m_object != nullptr);
13802 
13803 switch (m_object->m_data.m_type)
13804 {
13805 case value_t::object:
13806 {
13807 m_it.object_iterator = m_object->m_data.m_value.object->end();
13808 break;
13809 }
13810 
13811 case value_t::array:
13812 {
13813 m_it.array_iterator = m_object->m_data.m_value.array->end();
13814 break;
13815 }
13816 
13817 case value_t::null:
13818 case value_t::string:
13819 case value_t::boolean:
13820 case value_t::number_integer:
13821 case value_t::number_unsigned:
13822 case value_t::number_float:
13823 case value_t::binary:
13824 case value_t::discarded:
13825 default:
13826 {
13827 m_it.primitive_iterator.set_end();
13828 break;
13829 }
13830 }
13831 }
13832 
13833 public:
13834 /*!
13835 @brief return a reference to the value pointed to by the iterator
13836 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13837 */
13838 reference operator*() const
13839 {
13840 JSON_ASSERT(m_object != nullptr);
13841 
13842 switch (m_object->m_data.m_type)
13843 {
13844 case value_t::object:
13845 {
13846 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13847 return m_it.object_iterator->second;
13848 }
13849 
13850 case value_t::array:
13851 {
13852 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13853 return *m_it.array_iterator;
13854 }
13855 
13856 case value_t::null:
13857 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13858 
13859 case value_t::string:
13860 case value_t::boolean:
13861 case value_t::number_integer:
13862 case value_t::number_unsigned:
13863 case value_t::number_float:
13864 case value_t::binary:
13865 case value_t::discarded:
13866 default:
13867 {
13868 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13869 {
13870 return *m_object;
13871 }
13872 
13873 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13874 }
13875 }
13876 }
13877 
13878 /*!
13879 @brief dereference the iterator
13880 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13881 */
13882 pointer operator->() const
13883 {
13884 JSON_ASSERT(m_object != nullptr);
13885 
13886 switch (m_object->m_data.m_type)
13887 {
13888 case value_t::object:
13889 {
13890 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13891 return &(m_it.object_iterator->second);
13892 }
13893 
13894 case value_t::array:
13895 {
13896 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13897 return &*m_it.array_iterator;
13898 }
13899 
13900 case value_t::null:
13901 case value_t::string:
13902 case value_t::boolean:
13903 case value_t::number_integer:
13904 case value_t::number_unsigned:
13905 case value_t::number_float:
13906 case value_t::binary:
13907 case value_t::discarded:
13908 default:
13909 {
13910 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13911 {
13912 return m_object;
13913 }
13914 
13915 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13916 }
13917 }
13918 }
13919 
13920 /*!
13921 @brief post-increment (it++)
13922 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13923 */
13924 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13925 {
13926 auto result = *this;
13927 ++(*this);
13928 return result;
13929 }
13930 
13931 /*!
13932 @brief pre-increment (++it)
13933 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13934 */
13935 iter_impl& operator++()
13936 {
13937 JSON_ASSERT(m_object != nullptr);
13938 
13939 switch (m_object->m_data.m_type)
13940 {
13941 case value_t::object:
13942 {
13943 std::advance(m_it.object_iterator, 1);
13944 break;
13945 }
13946 
13947 case value_t::array:
13948 {
13949 std::advance(m_it.array_iterator, 1);
13950 break;
13951 }
13952 
13953 case value_t::null:
13954 case value_t::string:
13955 case value_t::boolean:
13956 case value_t::number_integer:
13957 case value_t::number_unsigned:
13958 case value_t::number_float:
13959 case value_t::binary:
13960 case value_t::discarded:
13961 default:
13962 {
13963 ++m_it.primitive_iterator;
13964 break;
13965 }
13966 }
13967 
13968 return *this;
13969 }
13970 
13971 /*!
13972 @brief post-decrement (it--)
13973 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13974 */
13975 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13976 {
13977 auto result = *this;
13978 --(*this);
13979 return result;
13980 }
13981 
13982 /*!
13983 @brief pre-decrement (--it)
13984 @pre The iterator is initialized; i.e. `m_object != nullptr`.
13985 */
13986 iter_impl& operator--()
13987 {
13988 JSON_ASSERT(m_object != nullptr);
13989 
13990 switch (m_object->m_data.m_type)
13991 {
13992 case value_t::object:
13993 {
13994 std::advance(m_it.object_iterator, -1);
13995 break;
13996 }
13997 
13998 case value_t::array:
13999 {
14000 std::advance(m_it.array_iterator, -1);
14001 break;
14002 }
14003 
14004 case value_t::null:
14005 case value_t::string:
14006 case value_t::boolean:
14007 case value_t::number_integer:
14008 case value_t::number_unsigned:
14009 case value_t::number_float:
14010 case value_t::binary:
14011 case value_t::discarded:
14012 default:
14013 {
14014 --m_it.primitive_iterator;
14015 break;
14016 }
14017 }
14018 
14019 return *this;
14020 }
14021 
14022 /*!
14023 @brief comparison: equal
14024 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14025 */
14026 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 >
14027 bool operator==(const IterImpl& other) const
14028 {
14029 // if objects are not the same, the comparison is undefined
14030 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14031 {
14032 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14033 }
14034 
14035 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14036 if (m_object == nullptr)
14037 {
14038 return true;
14039 }
14040 
14041 switch (m_object->m_data.m_type)
14042 {
14043 case value_t::object:
14044 return (m_it.object_iterator == other.m_it.object_iterator);
14045 
14046 case value_t::array:
14047 return (m_it.array_iterator == other.m_it.array_iterator);
14048 
14049 case value_t::null:
14050 case value_t::string:
14051 case value_t::boolean:
14052 case value_t::number_integer:
14053 case value_t::number_unsigned:
14054 case value_t::number_float:
14055 case value_t::binary:
14056 case value_t::discarded:
14057 default:
14058 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14059 }
14060 }
14061 
14062 /*!
14063 @brief comparison: not equal
14064 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14065 */
14066 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 >
14067 bool operator!=(const IterImpl& other) const
14068 {
14069 return !operator==(other);
14070 }
14071 
14072 /*!
14073 @brief comparison: smaller
14074 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14075 */
14076 bool operator<(const iter_impl& other) const
14077 {
14078 // if objects are not the same, the comparison is undefined
14079 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14080 {
14081 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14082 }
14083 
14084 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14085 if (m_object == nullptr)
14086 {
14087 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14088 return false;
14089 }
14090 
14091 switch (m_object->m_data.m_type)
14092 {
14093 case value_t::object:
14094 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14095 
14096 case value_t::array:
14097 return (m_it.array_iterator < other.m_it.array_iterator);
14098 
14099 case value_t::null:
14100 case value_t::string:
14101 case value_t::boolean:
14102 case value_t::number_integer:
14103 case value_t::number_unsigned:
14104 case value_t::number_float:
14105 case value_t::binary:
14106 case value_t::discarded:
14107 default:
14108 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14109 }
14110 }
14111 
14112 /*!
14113 @brief comparison: less than or equal
14114 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14115 */
14116 bool operator<=(const iter_impl& other) const
14117 {
14118 return !other.operator < (*this);
14119 }
14120 
14121 /*!
14122 @brief comparison: greater than
14123 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14124 */
14125 bool operator>(const iter_impl& other) const
14126 {
14127 return !operator<=(other);
14128 }
14129 
14130 /*!
14131 @brief comparison: greater than or equal
14132 @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized.
14133 */
14134 bool operator>=(const iter_impl& other) const
14135 {
14136 return !operator<(other);
14137 }
14138 
14139 /*!
14140 @brief add to iterator
14141 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14142 */
14143 iter_impl& operator+=(difference_type i)
14144 {
14145 JSON_ASSERT(m_object != nullptr);
14146 
14147 switch (m_object->m_data.m_type)
14148 {
14149 case value_t::object:
14150 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14151 
14152 case value_t::array:
14153 {
14154 std::advance(m_it.array_iterator, i);
14155 break;
14156 }
14157 
14158 case value_t::null:
14159 case value_t::string:
14160 case value_t::boolean:
14161 case value_t::number_integer:
14162 case value_t::number_unsigned:
14163 case value_t::number_float:
14164 case value_t::binary:
14165 case value_t::discarded:
14166 default:
14167 {
14168 m_it.primitive_iterator += i;
14169 break;
14170 }
14171 }
14172 
14173 return *this;
14174 }
14175 
14176 /*!
14177 @brief subtract from iterator
14178 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14179 */
14180 iter_impl& operator-=(difference_type i)
14181 {
14182 return operator+=(-i);
14183 }
14184 
14185 /*!
14186 @brief add to iterator
14187 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14188 */
14189 iter_impl operator+(difference_type i) const
14190 {
14191 auto result = *this;
14192 result += i;
14193 return result;
14194 }
14195 
14196 /*!
14197 @brief addition of distance and iterator
14198 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14199 */
14200 friend iter_impl operator+(difference_type i, const iter_impl& it)
14201 {
14202 auto result = it;
14203 result += i;
14204 return result;
14205 }
14206 
14207 /*!
14208 @brief subtract from iterator
14209 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14210 */
14211 iter_impl operator-(difference_type i) const
14212 {
14213 auto result = *this;
14214 result -= i;
14215 return result;
14216 }
14217 
14218 /*!
14219 @brief return difference
14220 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14221 */
14222 difference_type operator-(const iter_impl& other) const
14223 {
14224 JSON_ASSERT(m_object != nullptr);
14225 
14226 switch (m_object->m_data.m_type)
14227 {
14228 case value_t::object:
14229 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14230 
14231 case value_t::array:
14232 return m_it.array_iterator - other.m_it.array_iterator;
14233 
14234 case value_t::null:
14235 case value_t::string:
14236 case value_t::boolean:
14237 case value_t::number_integer:
14238 case value_t::number_unsigned:
14239 case value_t::number_float:
14240 case value_t::binary:
14241 case value_t::discarded:
14242 default:
14243 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14244 }
14245 }
14246 
14247 /*!
14248 @brief access to successor
14249 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14250 */
14251 reference operator[](difference_type n) const
14252 {
14253 JSON_ASSERT(m_object != nullptr);
14254 
14255 switch (m_object->m_data.m_type)
14256 {
14257 case value_t::object:
14258 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14259 
14260 case value_t::array:
14261 return *std::next(m_it.array_iterator, n);
14262 
14263 case value_t::null:
14264 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14265 
14266 case value_t::string:
14267 case value_t::boolean:
14268 case value_t::number_integer:
14269 case value_t::number_unsigned:
14270 case value_t::number_float:
14271 case value_t::binary:
14272 case value_t::discarded:
14273 default:
14274 {
14275 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14276 {
14277 return *m_object;
14278 }
14279 
14280 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14281 }
14282 }
14283 }
14284 
14285 /*!
14286 @brief return the key of an object iterator
14287 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14288 */
14289 const typename object_t::key_type& key() const
14290 {
14291 JSON_ASSERT(m_object != nullptr);
14292 
14293 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14294 {
14295 return m_it.object_iterator->first;
14296 }
14297 
14298 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14299 }
14300 
14301 /*!
14302 @brief return the value of an iterator
14303 @pre The iterator is initialized; i.e. `m_object != nullptr`.
14304 */
14305 reference value() const
14306 {
14307 return operator*();
14308 }
14309 
14310 JSON_PRIVATE_UNLESS_TESTED:
14311 /// associated JSON instance
14312 pointer m_object = nullptr;
14313 /// the actual iterator of the associated instance
14314 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
14315};
14316 
14317} // namespace detail
14318NLOHMANN_JSON_NAMESPACE_END
14319 
14320// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14321 
14322// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14323// __ _____ _____ _____
14324// __| | __| | | | JSON for Modern C++
14325// | | |__ | | | | | | version 3.12.0
14326// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14327//
14328// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14329// SPDX-License-Identifier: MIT
14330 
14331 
14332 
14333#include <cstddef> // ptrdiff_t
14334#include <iterator> // reverse_iterator
14335#include <utility> // declval
14336 
14337// #include <nlohmann/detail/abi_macros.hpp>
14338 
14339 
14340NLOHMANN_JSON_NAMESPACE_BEGIN
14341namespace detail
14342{
14343 
14344//////////////////////
14345// reverse_iterator //
14346//////////////////////
14347 
14348/*!
14349@brief a template for a reverse iterator class
14350 
14351@tparam Base the base iterator type to reverse. Valid types are @ref
14352iterator (to create @ref reverse_iterator) and @ref const_iterator (to
14353create @ref const_reverse_iterator).
14354 
14355@requirement The class satisfies the following concept requirements:
14356-
14357[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
14358 The iterator that can be moved can be moved in both directions (i.e.
14359 incremented and decremented).
14360- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
14361 It is possible to write to the pointed-to element (only if @a Base is
14362 @ref iterator).
14363 
14364@since version 1.0.0
14365*/
14366template<typename Base>
14367class json_reverse_iterator : public std::reverse_iterator<Base>
14368{
14369 public:
14370 using difference_type = std::ptrdiff_t;
14371 /// shortcut to the reverse iterator adapter
14372 using base_iterator = std::reverse_iterator<Base>;
14373 /// the reference type for the pointed-to element
14374 using reference = typename Base::reference;
14375 
14376 /// create reverse iterator from iterator
14377 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14378 : base_iterator(it) {}
14379 
14380 /// create reverse iterator from base class
14381 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14382 
14383 /// post-increment (it++)
14384 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14385 {
14386 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14387 }
14388 
14389 /// pre-increment (++it)
14390 json_reverse_iterator& operator++()
14391 {
14392 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14393 }
14394 
14395 /// post-decrement (it--)
14396 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14397 {
14398 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14399 }
14400 
14401 /// pre-decrement (--it)
14402 json_reverse_iterator& operator--()
14403 {
14404 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14405 }
14406 
14407 /// add to iterator
14408 json_reverse_iterator& operator+=(difference_type i)
14409 {
14410 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14411 }
14412 
14413 /// add to iterator
14414 json_reverse_iterator operator+(difference_type i) const
14415 {
14416 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14417 }
14418 
14419 /// subtract from iterator
14420 json_reverse_iterator operator-(difference_type i) const
14421 {
14422 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14423 }
14424 
14425 /// return difference
14426 difference_type operator-(const json_reverse_iterator& other) const
14427 {
14428 return base_iterator(*this) - base_iterator(other);
14429 }
14430 
14431 /// access to successor
14432 reference operator[](difference_type n) const
14433 {
14434 return *(this->operator+(n));
14435 }
14436 
14437 /// return the key of an object iterator
14438 auto key() const -> decltype(std::declval<Base>().key())
14439 {
14440 auto it = --this->base();
14441 return it.key();
14442 }
14443 
14444 /// return the value of an iterator
14445 reference value() const
14446 {
14447 auto it = --this->base();
14448 return it.operator * ();
14449 }
14450};
14451 
14452} // namespace detail
14453NLOHMANN_JSON_NAMESPACE_END
14454 
14455// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14456 
14457// #include <nlohmann/detail/json_custom_base_class.hpp>
14458// __ _____ _____ _____
14459// __| | __| | | | JSON for Modern C++
14460// | | |__ | | | | | | version 3.12.0
14461// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14462//
14463// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14464// SPDX-License-Identifier: MIT
14465 
14466 
14467 
14468#include <type_traits> // conditional, is_same
14469 
14470// #include <nlohmann/detail/abi_macros.hpp>
14471 
14472 
14473NLOHMANN_JSON_NAMESPACE_BEGIN
14474namespace detail
14475{
14476 
14477/*!
14478@brief Default base class of the @ref basic_json class.
14479 
14480So that the correct implementations of the copy / move ctors / assign operators
14481of @ref basic_json do not require complex case distinctions
14482(no base class / custom base class used as customization point),
14483@ref basic_json always has a base class.
14484By default, this class is used because it is empty and thus has no effect
14485on the behavior of @ref basic_json.
14486*/
14487struct json_default_base {};
14488 
14489template<class T>
14490using json_base_class = typename std::conditional <
14491 std::is_same<T, void>::value,
14492 json_default_base,
14493 T
14494 >::type;
14495 
14496} // namespace detail
14497NLOHMANN_JSON_NAMESPACE_END
14498 
14499// #include <nlohmann/detail/json_pointer.hpp>
14500// __ _____ _____ _____
14501// __| | __| | | | JSON for Modern C++
14502// | | |__ | | | | | | version 3.12.0
14503// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14504//
14505// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14506// SPDX-License-Identifier: MIT
14507 
14508 
14509 
14510#include <algorithm> // all_of
14511#include <cctype> // isdigit
14512#include <cerrno> // errno, ERANGE
14513#include <cstdlib> // strtoull
14514#ifndef JSON_NO_IO
14515 #include <iosfwd> // ostream
14516#endif // JSON_NO_IO
14517#include <limits> // max
14518#include <numeric> // accumulate
14519#include <string> // string
14520#include <utility> // move
14521#include <vector> // vector
14522 
14523// #include <nlohmann/detail/exceptions.hpp>
14524 
14525// #include <nlohmann/detail/macro_scope.hpp>
14526 
14527// #include <nlohmann/detail/string_concat.hpp>
14528 
14529// #include <nlohmann/detail/string_escape.hpp>
14530 
14531// #include <nlohmann/detail/value_t.hpp>
14532 
14533 
14534NLOHMANN_JSON_NAMESPACE_BEGIN
14535 
14536/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
14537/// @sa https://json.nlohmann.me/api/json_pointer/
14538template<typename RefStringType>
14539class json_pointer
14540{
14541 // allow basic_json to access private members
14542 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14543 friend class basic_json;
14544 
14545 template<typename>
14546 friend class json_pointer;
14547 
14548 template<typename T>
14549 struct string_t_helper
14550 {
14551 using type = T;
14552 };
14553 
14554 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14555 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14556 {
14557 using type = StringType;
14558 };
14559 
14560 public:
14561 // for backwards compatibility accept BasicJsonType
14562 using string_t = typename string_t_helper<RefStringType>::type;
14563 
14564 /// @brief create JSON pointer
14565 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
14566 explicit json_pointer(const string_t& s = "")
14567 : reference_tokens(split(s))
14568 {}
14569 
14570 /// @brief return a string representation of the JSON pointer
14571 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
14572 string_t to_string() const
14573 {
14574 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14575 string_t{},
14576 [](const string_t& a, const string_t& b)
14577 {
14578 return detail::concat(a, '/', detail::escape(b));
14579 });
14580 }
14581 
14582 /// @brief return a string representation of the JSON pointer
14583 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
14584 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
14585 operator string_t() const
14586 {
14587 return to_string();
14588 }
14589 
14590#ifndef JSON_NO_IO
14591 /// @brief write string representation of the JSON pointer to stream
14592 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
14593 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14594 {
14595 o << ptr.to_string();
14596 return o;
14597 }
14598#endif
14599 
14600 /// @brief append another JSON pointer at the end of this JSON pointer
14601 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14602 json_pointer& operator/=(const json_pointer& ptr)
14603 {
14604 reference_tokens.insert(reference_tokens.end(),
14605 ptr.reference_tokens.begin(),
14606 ptr.reference_tokens.end());
14607 return *this;
14608 }
14609 
14610 /// @brief append an unescaped reference token at the end of this JSON pointer
14611 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14612 json_pointer& operator/=(string_t token)
14613 {
14614 push_back(std::move(token));
14615 return *this;
14616 }
14617 
14618 /// @brief append an array index at the end of this JSON pointer
14619 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14620 json_pointer& operator/=(std::size_t array_idx)
14621 {
14622 return *this /= std::to_string(array_idx);
14623 }
14624 
14625 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
14626 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14627 friend json_pointer operator/(const json_pointer& lhs,
14628 const json_pointer& rhs)
14629 {
14630 return json_pointer(lhs) /= rhs;
14631 }
14632 
14633 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
14634 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14635 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14636 {
14637 return json_pointer(lhs) /= std::move(token);
14638 }
14639 
14640 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
14641 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14642 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14643 {
14644 return json_pointer(lhs) /= array_idx;
14645 }
14646 
14647 /// @brief returns the parent of this JSON pointer
14648 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
14649 json_pointer parent_pointer() const
14650 {
14651 if (empty())
14652 {
14653 return *this;
14654 }
14655 
14656 json_pointer res = *this;
14657 res.pop_back();
14658 return res;
14659 }
14660 
14661 /// @brief remove last reference token
14662 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
14663 void pop_back()
14664 {
14665 if (JSON_HEDLEY_UNLIKELY(empty()))
14666 {
14667 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14668 }
14669 
14670 reference_tokens.pop_back();
14671 }
14672 
14673 /// @brief return last reference token
14674 /// @sa https://json.nlohmann.me/api/json_pointer/back/
14675 const string_t& back() const
14676 {
14677 if (JSON_HEDLEY_UNLIKELY(empty()))
14678 {
14679 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14680 }
14681 
14682 return reference_tokens.back();
14683 }
14684 
14685 /// @brief append an unescaped token at the end of the reference pointer
14686 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14687 void push_back(const string_t& token)
14688 {
14689 reference_tokens.push_back(token);
14690 }
14691 
14692 /// @brief append an unescaped token at the end of the reference pointer
14693 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14694 void push_back(string_t&& token)
14695 {
14696 reference_tokens.push_back(std::move(token));
14697 }
14698 
14699 /// @brief return whether pointer points to the root document
14700 /// @sa https://json.nlohmann.me/api/json_pointer/empty/
14701 bool empty() const noexcept
14702 {
14703 return reference_tokens.empty();
14704 }
14705 
14706 private:
14707 /*!
14708 @param[in] s reference token to be converted into an array index
14709 
14710 @return integer representation of @a s
14711 
14712 @throw parse_error.106 if an array index begins with '0'
14713 @throw parse_error.109 if an array index begins not with a digit
14714 @throw out_of_range.404 if string @a s could not be converted to an integer
14715 @throw out_of_range.410 if an array index exceeds size_type
14716 */
14717 template<typename BasicJsonType>
14718 static typename BasicJsonType::size_type array_index(const string_t& s)
14719 {
14720 using size_type = typename BasicJsonType::size_type;
14721 
14722 // error condition (cf. RFC 6901, Sect. 4)
14723 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14724 {
14725 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14726 }
14727 
14728 // error condition (cf. RFC 6901, Sect. 4)
14729 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14730 {
14731 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14732 }
14733 
14734 const char* p = s.c_str();
14735 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14736 errno = 0; // strtoull doesn't reset errno
14737 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14738 if (p == p_end // invalid input or empty string
14739 || errno == ERANGE // out of range
14740 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14741 {
14742 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14743 }
14744 
14745 // only triggered on special platforms (like 32bit), see also
14746 // https://github.com/nlohmann/json/pull/2203
14747 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14748 {
14749 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14750 }
14751 
14752 return static_cast<size_type>(res);
14753 }
14754 
14755 JSON_PRIVATE_UNLESS_TESTED:
14756 json_pointer top() const
14757 {
14758 if (JSON_HEDLEY_UNLIKELY(empty()))
14759 {
14760 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14761 }
14762 
14763 json_pointer result = *this;
14764 result.reference_tokens = {reference_tokens[0]};
14765 return result;
14766 }
14767 
14768 private:
14769 /*!
14770 @brief create and return a reference to the pointed to value
14771 
14772 @complexity Linear in the number of reference tokens.
14773 
14774 @throw parse_error.109 if array index is not a number
14775 @throw type_error.313 if value cannot be unflattened
14776 */
14777 template<typename BasicJsonType>
14778 BasicJsonType& get_and_create(BasicJsonType& j) const
14779 {
14780 auto* result = &j;
14781 
14782 // in case no reference tokens exist, return a reference to the JSON value
14783 // j which will be overwritten by a primitive value
14784 for (const auto& reference_token : reference_tokens)
14785 {
14786 switch (result->type())
14787 {
14788 case detail::value_t::null:
14789 {
14790 if (reference_token == "0")
14791 {
14792 // start a new array if reference token is 0
14793 result = &result->operator[](0);
14794 }
14795 else
14796 {
14797 // start a new object otherwise
14798 result = &result->operator[](reference_token);
14799 }
14800 break;
14801 }
14802 
14803 case detail::value_t::object:
14804 {
14805 // create an entry in the object
14806 result = &result->operator[](reference_token);
14807 break;
14808 }
14809 
14810 case detail::value_t::array:
14811 {
14812 // create an entry in the array
14813 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14814 break;
14815 }
14816 
14817 /*
14818 The following code is only reached if there exists a reference
14819 token _and_ the current value is primitive. In this case, we have
14820 an error situation, because primitive values may only occur as
14821 single value; that is, with an empty list of reference tokens.
14822 */
14823 case detail::value_t::string:
14824 case detail::value_t::boolean:
14825 case detail::value_t::number_integer:
14826 case detail::value_t::number_unsigned:
14827 case detail::value_t::number_float:
14828 case detail::value_t::binary:
14829 case detail::value_t::discarded:
14830 default:
14831 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14832 }
14833 }
14834 
14835 return *result;
14836 }
14837 
14838 /*!
14839 @brief return a reference to the pointed to value
14840 
14841 @note This version does not throw if a value is not present, but tries to
14842 create nested values instead. For instance, calling this function
14843 with pointer `"/this/that"` on a null value is equivalent to calling
14844 `operator[]("this").operator[]("that")` on that value, effectively
14845 changing the null value to an object.
14846 
14847 @param[in] ptr a JSON value
14848 
14849 @return reference to the JSON value pointed to by the JSON pointer
14850 
14851 @complexity Linear in the length of the JSON pointer.
14852 
14853 @throw parse_error.106 if an array index begins with '0'
14854 @throw parse_error.109 if an array index was not a number
14855 @throw out_of_range.404 if the JSON pointer can not be resolved
14856 */
14857 template<typename BasicJsonType>
14858 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14859 {
14860 for (const auto& reference_token : reference_tokens)
14861 {
14862 // convert null values to arrays or objects before continuing
14863 if (ptr->is_null())
14864 {
14865 // check if reference token is a number
14866 const bool nums =
14867 std::all_of(reference_token.begin(), reference_token.end(),
14868 [](const unsigned char x)
14869 {
14870 return std::isdigit(x);
14871 });
14872 
14873 // change value to array for numbers or "-" or to object otherwise
14874 *ptr = (nums || reference_token == "-")
14875 ? detail::value_t::array
14876 : detail::value_t::object;
14877 }
14878 
14879 switch (ptr->type())
14880 {
14881 case detail::value_t::object:
14882 {
14883 // use unchecked object access
14884 ptr = &ptr->operator[](reference_token);
14885 break;
14886 }
14887 
14888 case detail::value_t::array:
14889 {
14890 if (reference_token == "-")
14891 {
14892 // explicitly treat "-" as index beyond the end
14893 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14894 }
14895 else
14896 {
14897 // convert array index to number; unchecked access
14898 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14899 }
14900 break;
14901 }
14902 
14903 case detail::value_t::null:
14904 case detail::value_t::string:
14905 case detail::value_t::boolean:
14906 case detail::value_t::number_integer:
14907 case detail::value_t::number_unsigned:
14908 case detail::value_t::number_float:
14909 case detail::value_t::binary:
14910 case detail::value_t::discarded:
14911 default:
14912 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14913 }
14914 }
14915 
14916 return *ptr;
14917 }
14918 
14919 /*!
14920 @throw parse_error.106 if an array index begins with '0'
14921 @throw parse_error.109 if an array index was not a number
14922 @throw out_of_range.402 if the array index '-' is used
14923 @throw out_of_range.404 if the JSON pointer can not be resolved
14924 */
14925 template<typename BasicJsonType>
14926 BasicJsonType& get_checked(BasicJsonType* ptr) const
14927 {
14928 for (const auto& reference_token : reference_tokens)
14929 {
14930 switch (ptr->type())
14931 {
14932 case detail::value_t::object:
14933 {
14934 // note: at performs range check
14935 ptr = &ptr->at(reference_token);
14936 break;
14937 }
14938 
14939 case detail::value_t::array:
14940 {
14941 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14942 {
14943 // "-" always fails the range check
14944 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14945 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14946 ") is out of range"), ptr));
14947 }
14948 
14949 // note: at performs range check
14950 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14951 break;
14952 }
14953 
14954 case detail::value_t::null:
14955 case detail::value_t::string:
14956 case detail::value_t::boolean:
14957 case detail::value_t::number_integer:
14958 case detail::value_t::number_unsigned:
14959 case detail::value_t::number_float:
14960 case detail::value_t::binary:
14961 case detail::value_t::discarded:
14962 default:
14963 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14964 }
14965 }
14966 
14967 return *ptr;
14968 }
14969 
14970 /*!
14971 @brief return a const reference to the pointed to value
14972 
14973 @param[in] ptr a JSON value
14974 
14975 @return const reference to the JSON value pointed to by the JSON
14976 pointer
14977 
14978 @throw parse_error.106 if an array index begins with '0'
14979 @throw parse_error.109 if an array index was not a number
14980 @throw out_of_range.402 if the array index '-' is used
14981 @throw out_of_range.404 if the JSON pointer can not be resolved
14982 */
14983 template<typename BasicJsonType>
14984 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14985 {
14986 for (const auto& reference_token : reference_tokens)
14987 {
14988 switch (ptr->type())
14989 {
14990 case detail::value_t::object:
14991 {
14992 // use unchecked object access
14993 ptr = &ptr->operator[](reference_token);
14994 break;
14995 }
14996 
14997 case detail::value_t::array:
14998 {
14999 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15000 {
15001 // "-" cannot be used for const access
15002 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));
15003 }
15004 
15005 // use unchecked array access
15006 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15007 break;
15008 }
15009 
15010 case detail::value_t::null:
15011 case detail::value_t::string:
15012 case detail::value_t::boolean:
15013 case detail::value_t::number_integer:
15014 case detail::value_t::number_unsigned:
15015 case detail::value_t::number_float:
15016 case detail::value_t::binary:
15017 case detail::value_t::discarded:
15018 default:
15019 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15020 }
15021 }
15022 
15023 return *ptr;
15024 }
15025 
15026 /*!
15027 @throw parse_error.106 if an array index begins with '0'
15028 @throw parse_error.109 if an array index was not a number
15029 @throw out_of_range.402 if the array index '-' is used
15030 @throw out_of_range.404 if the JSON pointer can not be resolved
15031 */
15032 template<typename BasicJsonType>
15033 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15034 {
15035 for (const auto& reference_token : reference_tokens)
15036 {
15037 switch (ptr->type())
15038 {
15039 case detail::value_t::object:
15040 {
15041 // note: at performs range check
15042 ptr = &ptr->at(reference_token);
15043 break;
15044 }
15045 
15046 case detail::value_t::array:
15047 {
15048 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15049 {
15050 // "-" always fails the range check
15051 JSON_THROW(detail::out_of_range::create(402, detail::concat(
15052 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15053 ") is out of range"), ptr));
15054 }
15055 
15056 // note: at performs range check
15057 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15058 break;
15059 }
15060 
15061 case detail::value_t::null:
15062 case detail::value_t::string:
15063 case detail::value_t::boolean:
15064 case detail::value_t::number_integer:
15065 case detail::value_t::number_unsigned:
15066 case detail::value_t::number_float:
15067 case detail::value_t::binary:
15068 case detail::value_t::discarded:
15069 default:
15070 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15071 }
15072 }
15073 
15074 return *ptr;
15075 }
15076 
15077 /*!
15078 @throw parse_error.106 if an array index begins with '0'
15079 @throw parse_error.109 if an array index was not a number
15080 */
15081 template<typename BasicJsonType>
15082 bool contains(const BasicJsonType* ptr) const
15083 {
15084 for (const auto& reference_token : reference_tokens)
15085 {
15086 switch (ptr->type())
15087 {
15088 case detail::value_t::object:
15089 {
15090 if (!ptr->contains(reference_token))
15091 {
15092 // we did not find the key in the object
15093 return false;
15094 }
15095 
15096 ptr = &ptr->operator[](reference_token);
15097 break;
15098 }
15099 
15100 case detail::value_t::array:
15101 {
15102 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15103 {
15104 // "-" always fails the range check
15105 return false;
15106 }
15107 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15108 {
15109 // invalid char
15110 return false;
15111 }
15112 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15113 {
15114 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15115 {
15116 // first char should be between '1' and '9'
15117 return false;
15118 }
15119 for (std::size_t i = 1; i < reference_token.size(); i++)
15120 {
15121 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15122 {
15123 // other char should be between '0' and '9'
15124 return false;
15125 }
15126 }
15127 }
15128 
15129 const auto idx = array_index<BasicJsonType>(reference_token);
15130 if (idx >= ptr->size())
15131 {
15132 // index out of range
15133 return false;
15134 }
15135 
15136 ptr = &ptr->operator[](idx);
15137 break;
15138 }
15139 
15140 case detail::value_t::null:
15141 case detail::value_t::string:
15142 case detail::value_t::boolean:
15143 case detail::value_t::number_integer:
15144 case detail::value_t::number_unsigned:
15145 case detail::value_t::number_float:
15146 case detail::value_t::binary:
15147 case detail::value_t::discarded:
15148 default:
15149 {
15150 // we do not expect primitive values if there is still a
15151 // reference token to process
15152 return false;
15153 }
15154 }
15155 }
15156 
15157 // no reference token left means we found a primitive value
15158 return true;
15159 }
15160 
15161 /*!
15162 @brief split the string input to reference tokens
15163 
15164 @note This function is only called by the json_pointer constructor.
15165 All exceptions below are documented there.
15166 
15167 @throw parse_error.107 if the pointer is not empty or begins with '/'
15168 @throw parse_error.108 if character '~' is not followed by '0' or '1'
15169 */
15170 static std::vector<string_t> split(const string_t& reference_string)
15171 {
15172 std::vector<string_t> result;
15173 
15174 // special case: empty reference string -> no reference tokens
15175 if (reference_string.empty())
15176 {
15177 return result;
15178 }
15179 
15180 // check if nonempty reference string begins with slash
15181 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15182 {
15183 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15184 }
15185 
15186 // extract the reference tokens:
15187 // - slash: position of the last read slash (or end of string)
15188 // - start: position after the previous slash
15189 for (
15190 // search for the first slash after the first character
15191 std::size_t slash = reference_string.find_first_of('/', 1),
15192 // set the beginning of the first reference token
15193 start = 1;
15194 // we can stop if start == 0 (if slash == string_t::npos)
15195 start != 0;
15196 // set the beginning of the next reference token
15197 // (will eventually be 0 if slash == string_t::npos)
15198 start = (slash == string_t::npos) ? 0 : slash + 1,
15199 // find next slash
15200 slash = reference_string.find_first_of('/', start))
15201 {
15202 // use the text between the beginning of the reference token
15203 // (start) and the last slash (slash).
15204 auto reference_token = reference_string.substr(start, slash - start);
15205 
15206 // check reference tokens are properly escaped
15207 for (std::size_t pos = reference_token.find_first_of('~');
15208 pos != string_t::npos;
15209 pos = reference_token.find_first_of('~', pos + 1))
15210 {
15211 JSON_ASSERT(reference_token[pos] == '~');
15212 
15213 // ~ must be followed by 0 or 1
15214 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15215 (reference_token[pos + 1] != '0' &&
15216 reference_token[pos + 1] != '1')))
15217 {
15218 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15219 }
15220 }
15221 
15222 // finally, store the reference token
15223 detail::unescape(reference_token);
15224 result.push_back(reference_token);
15225 }
15226 
15227 return result;
15228 }
15229 
15230 private:
15231 /*!
15232 @param[in] reference_string the reference string to the current value
15233 @param[in] value the value to consider
15234 @param[in,out] result the result object to insert values to
15235 
15236 @note Empty objects or arrays are flattened to `null`.
15237 */
15238 template<typename BasicJsonType>
15239 static void flatten(const string_t& reference_string,
15240 const BasicJsonType& value,
15241 BasicJsonType& result)
15242 {
15243 switch (value.type())
15244 {
15245 case detail::value_t::array:
15246 {
15247 if (value.m_data.m_value.array->empty())
15248 {
15249 // flatten empty array as null
15250 result[reference_string] = nullptr;
15251 }
15252 else
15253 {
15254 // iterate array and use index as reference string
15255 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15256 {
15257 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15258 value.m_data.m_value.array->operator[](i), result);
15259 }
15260 }
15261 break;
15262 }
15263 
15264 case detail::value_t::object:
15265 {
15266 if (value.m_data.m_value.object->empty())
15267 {
15268 // flatten empty object as null
15269 result[reference_string] = nullptr;
15270 }
15271 else
15272 {
15273 // iterate object and use keys as reference string
15274 for (const auto& element : *value.m_data.m_value.object)
15275 {
15276 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15277 }
15278 }
15279 break;
15280 }
15281 
15282 case detail::value_t::null:
15283 case detail::value_t::string:
15284 case detail::value_t::boolean:
15285 case detail::value_t::number_integer:
15286 case detail::value_t::number_unsigned:
15287 case detail::value_t::number_float:
15288 case detail::value_t::binary:
15289 case detail::value_t::discarded:
15290 default:
15291 {
15292 // add primitive value with its reference string
15293 result[reference_string] = value;
15294 break;
15295 }
15296 }
15297 }
15298 
15299 /*!
15300 @param[in] value flattened JSON
15301 
15302 @return unflattened JSON
15303 
15304 @throw parse_error.109 if array index is not a number
15305 @throw type_error.314 if value is not an object
15306 @throw type_error.315 if object values are not primitive
15307 @throw type_error.313 if value cannot be unflattened
15308 */
15309 template<typename BasicJsonType>
15310 static BasicJsonType
15311 unflatten(const BasicJsonType& value)
15312 {
15313 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15314 {
15315 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15316 }
15317 
15318 BasicJsonType result;
15319 
15320 // iterate the JSON object values
15321 for (const auto& element : *value.m_data.m_value.object)
15322 {
15323 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15324 {
15325 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15326 }
15327 
15328 // assign value to reference pointed to by JSON pointer; Note that if
15329 // the JSON pointer is "" (i.e., points to the whole value), function
15330 // get_and_create returns a reference to result itself. An assignment
15331 // will then create a primitive value.
15332 json_pointer(element.first).get_and_create(result) = element.second;
15333 }
15334 
15335 return result;
15336 }
15337 
15338 // can't use conversion operator because of ambiguity
15339 json_pointer<string_t> convert() const&
15340 {
15341 json_pointer<string_t> result;
15342 result.reference_tokens = reference_tokens;
15343 return result;
15344 }
15345 
15346 json_pointer<string_t> convert()&&
15347 {
15348 json_pointer<string_t> result;
15349 result.reference_tokens = std::move(reference_tokens);
15350 return result;
15351 }
15352 
15353 public:
15354#if JSON_HAS_THREE_WAY_COMPARISON
15355 /// @brief compares two JSON pointers for equality
15356 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15357 template<typename RefStringTypeRhs>
15358 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15359 {
15360 return reference_tokens == rhs.reference_tokens;
15361 }
15362 
15363 /// @brief compares JSON pointer and string for equality
15364 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15365 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15366 bool operator==(const string_t& rhs) const
15367 {
15368 return *this == json_pointer(rhs);
15369 }
15370 
15371 /// @brief 3-way compares two JSON pointers
15372 template<typename RefStringTypeRhs>
15373 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15374 {
15375 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15376 }
15377#else
15378 /// @brief compares two JSON pointers for equality
15379 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15380 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15381 // NOLINTNEXTLINE(readability-redundant-declaration)
15382 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15383 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15384 
15385 /// @brief compares JSON pointer and string for equality
15386 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15387 template<typename RefStringTypeLhs, typename StringType>
15388 // NOLINTNEXTLINE(readability-redundant-declaration)
15389 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15390 const StringType& rhs);
15391 
15392 /// @brief compares string and JSON pointer for equality
15393 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15394 template<typename RefStringTypeRhs, typename StringType>
15395 // NOLINTNEXTLINE(readability-redundant-declaration)
15396 friend bool operator==(const StringType& lhs,
15397 const json_pointer<RefStringTypeRhs>& rhs);
15398 
15399 /// @brief compares two JSON pointers for inequality
15400 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15401 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15402 // NOLINTNEXTLINE(readability-redundant-declaration)
15403 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15404 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15405 
15406 /// @brief compares JSON pointer and string for inequality
15407 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15408 template<typename RefStringTypeLhs, typename StringType>
15409 // NOLINTNEXTLINE(readability-redundant-declaration)
15410 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15411 const StringType& rhs);
15412 
15413 /// @brief compares string and JSON pointer for inequality
15414 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15415 template<typename RefStringTypeRhs, typename StringType>
15416 // NOLINTNEXTLINE(readability-redundant-declaration)
15417 friend bool operator!=(const StringType& lhs,
15418 const json_pointer<RefStringTypeRhs>& rhs);
15419 
15420 /// @brief compares two JSON pointer for less-than
15421 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15422 // NOLINTNEXTLINE(readability-redundant-declaration)
15423 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15424 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15425#endif
15426 
15427 private:
15428 /// the reference tokens
15429 std::vector<string_t> reference_tokens;
15430};
15431 
15432#if !JSON_HAS_THREE_WAY_COMPARISON
15433// functions cannot be defined inside class due to ODR violations
15434template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15435inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15436 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15437{
15438 return lhs.reference_tokens == rhs.reference_tokens;
15439}
15440 
15441template<typename RefStringTypeLhs,
15442 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15443JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15444inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15445 const StringType& rhs)
15446{
15447 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15448}
15449 
15450template<typename RefStringTypeRhs,
15451 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15452JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15453inline bool operator==(const StringType& lhs,
15454 const json_pointer<RefStringTypeRhs>& rhs)
15455{
15456 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15457}
15458 
15459template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15460inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15461 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15462{
15463 return !(lhs == rhs);
15464}
15465 
15466template<typename RefStringTypeLhs,
15467 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15468JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15469inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15470 const StringType& rhs)
15471{
15472 return !(lhs == rhs);
15473}
15474 
15475template<typename RefStringTypeRhs,
15476 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15477JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15478inline bool operator!=(const StringType& lhs,
15479 const json_pointer<RefStringTypeRhs>& rhs)
15480{
15481 return !(lhs == rhs);
15482}
15483 
15484template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15485inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15486 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15487{
15488 return lhs.reference_tokens < rhs.reference_tokens;
15489}
15490#endif
15491 
15492NLOHMANN_JSON_NAMESPACE_END
15493 
15494// #include <nlohmann/detail/json_ref.hpp>
15495// __ _____ _____ _____
15496// __| | __| | | | JSON for Modern C++
15497// | | |__ | | | | | | version 3.12.0
15498// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15499//
15500// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15501// SPDX-License-Identifier: MIT
15502 
15503 
15504 
15505#include <initializer_list>
15506#include <utility>
15507 
15508// #include <nlohmann/detail/abi_macros.hpp>
15509 
15510// #include <nlohmann/detail/meta/type_traits.hpp>
15511 
15512 
15513NLOHMANN_JSON_NAMESPACE_BEGIN
15514namespace detail
15515{
15516 
15517template<typename BasicJsonType>
15518class json_ref
15519{
15520 public:
15521 using value_type = BasicJsonType;
15522 
15523 json_ref(value_type&& value)
15524 : owned_value(std::move(value))
15525 {}
15526 
15527 json_ref(const value_type& value)
15528 : value_ref(&value)
15529 {}
15530 
15531 json_ref(std::initializer_list<json_ref> init)
15532 : owned_value(init)
15533 {}
15534 
15535 template <
15536 class... Args,
15537 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15538 json_ref(Args && ... args)
15539 : owned_value(std::forward<Args>(args)...)
15540 {}
15541 
15542 // class should be movable only
15543 json_ref(json_ref&&) noexcept = default;
15544 json_ref(const json_ref&) = delete;
15545 json_ref& operator=(const json_ref&) = delete;
15546 json_ref& operator=(json_ref&&) = delete;
15547 ~json_ref() = default;
15548 
15549 value_type moved_or_copied() const
15550 {
15551 if (value_ref == nullptr)
15552 {
15553 return std::move(owned_value);
15554 }
15555 return *value_ref;
15556 }
15557 
15558 value_type const& operator*() const
15559 {
15560 return value_ref ? *value_ref : owned_value;
15561 }
15562 
15563 value_type const* operator->() const
15564 {
15565 return &** this;
15566 }
15567 
15568 private:
15569 mutable value_type owned_value = nullptr;
15570 value_type const* value_ref = nullptr;
15571};
15572 
15573} // namespace detail
15574NLOHMANN_JSON_NAMESPACE_END
15575 
15576// #include <nlohmann/detail/macro_scope.hpp>
15577 
15578// #include <nlohmann/detail/string_concat.hpp>
15579 
15580// #include <nlohmann/detail/string_escape.hpp>
15581 
15582// #include <nlohmann/detail/string_utils.hpp>
15583 
15584// #include <nlohmann/detail/meta/cpp_future.hpp>
15585 
15586// #include <nlohmann/detail/meta/type_traits.hpp>
15587 
15588// #include <nlohmann/detail/output/binary_writer.hpp>
15589// __ _____ _____ _____
15590// __| | __| | | | JSON for Modern C++
15591// | | |__ | | | | | | version 3.12.0
15592// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15593//
15594// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15595// SPDX-License-Identifier: MIT
15596 
15597 
15598 
15599#include <algorithm> // reverse
15600#include <array> // array
15601#include <map> // map
15602#include <cmath> // isnan, isinf
15603#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15604#include <cstring> // memcpy
15605#include <limits> // numeric_limits
15606#include <string> // string
15607#include <utility> // move
15608#include <vector> // vector
15609 
15610// #include <nlohmann/detail/input/binary_reader.hpp>
15611 
15612// #include <nlohmann/detail/macro_scope.hpp>
15613 
15614// #include <nlohmann/detail/output/output_adapters.hpp>
15615// __ _____ _____ _____
15616// __| | __| | | | JSON for Modern C++
15617// | | |__ | | | | | | version 3.12.0
15618// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15619//
15620// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15621// SPDX-License-Identifier: MIT
15622 
15623 
15624 
15625#include <algorithm> // copy
15626#include <cstddef> // size_t
15627#include <iterator> // back_inserter
15628#include <memory> // shared_ptr, make_shared
15629#include <string> // basic_string
15630#include <vector> // vector
15631 
15632#ifndef JSON_NO_IO
15633 #include <ios> // streamsize
15634 #include <ostream> // basic_ostream
15635#endif // JSON_NO_IO
15636 
15637// #include <nlohmann/detail/macro_scope.hpp>
15638 
15639 
15640NLOHMANN_JSON_NAMESPACE_BEGIN
15641namespace detail
15642{
15643 
15644/// abstract output adapter interface
15645template<typename CharType> struct output_adapter_protocol
15646{
15647 virtual void write_character(CharType c) = 0;
15648 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15649 virtual ~output_adapter_protocol() = default;
15650 
15651 output_adapter_protocol() = default;
15652 output_adapter_protocol(const output_adapter_protocol&) = default;
15653 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15654 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15655 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15656};
15657 
15658/// a type to simplify interfaces
15659template<typename CharType>
15660using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15661 
15662/// output adapter for byte vectors
15663template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15664class output_vector_adapter : public output_adapter_protocol<CharType>
15665{
15666 public:
15667 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15668 : v(vec)
15669 {}
15670 
15671 void write_character(CharType c) override
15672 {
15673 v.push_back(c);
15674 }
15675 
15676 JSON_HEDLEY_NON_NULL(2)
15677 void write_characters(const CharType* s, std::size_t length) override
15678 {
15679 v.insert(v.end(), s, s + length);
15680 }
15681 
15682 private:
15683 std::vector<CharType, AllocatorType>& v;
15684};
15685 
15686#ifndef JSON_NO_IO
15687/// output adapter for output streams
15688template<typename CharType>
15689class output_stream_adapter : public output_adapter_protocol<CharType>
15690{
15691 public:
15692 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15693 : stream(s)
15694 {}
15695 
15696 void write_character(CharType c) override
15697 {
15698 stream.put(c);
15699 }
15700 
15701 JSON_HEDLEY_NON_NULL(2)
15702 void write_characters(const CharType* s, std::size_t length) override
15703 {
15704 stream.write(s, static_cast<std::streamsize>(length));
15705 }
15706 
15707 private:
15708 std::basic_ostream<CharType>& stream;
15709};
15710#endif // JSON_NO_IO
15711 
15712/// output adapter for basic_string
15713template<typename CharType, typename StringType = std::basic_string<CharType>>
15714class output_string_adapter : public output_adapter_protocol<CharType>
15715{
15716 public:
15717 explicit output_string_adapter(StringType& s) noexcept
15718 : str(s)
15719 {}
15720 
15721 void write_character(CharType c) override
15722 {
15723 str.push_back(c);
15724 }
15725 
15726 JSON_HEDLEY_NON_NULL(2)
15727 void write_characters(const CharType* s, std::size_t length) override
15728 {
15729 str.append(s, length);
15730 }
15731 
15732 private:
15733 StringType& str;
15734};
15735 
15736template<typename CharType, typename StringType = std::basic_string<CharType>>
15737class output_adapter
15738{
15739 public:
15740 template<typename AllocatorType = std::allocator<CharType>>
15741 output_adapter(std::vector<CharType, AllocatorType>& vec)
15742 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15743 
15744#ifndef JSON_NO_IO
15745 output_adapter(std::basic_ostream<CharType>& s)
15746 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15747#endif // JSON_NO_IO
15748 
15749 output_adapter(StringType& s)
15750 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15751 
15752 operator output_adapter_t<CharType>()
15753 {
15754 return oa;
15755 }
15756 
15757 private:
15758 output_adapter_t<CharType> oa = nullptr;
15759};
15760 
15761} // namespace detail
15762NLOHMANN_JSON_NAMESPACE_END
15763 
15764// #include <nlohmann/detail/string_concat.hpp>
15765 
15766 
15767NLOHMANN_JSON_NAMESPACE_BEGIN
15768namespace detail
15769{
15770 
15771/// how to encode BJData
15772enum class bjdata_version_t
15773{
15774 draft2,
15775 draft3,
15776};
15777 
15778///////////////////
15779// binary writer //
15780///////////////////
15781 
15782/*!
15783@brief serialization to CBOR and MessagePack values
15784*/
15785template<typename BasicJsonType, typename CharType>
15786class binary_writer
15787{
15788 using string_t = typename BasicJsonType::string_t;
15789 using binary_t = typename BasicJsonType::binary_t;
15790 using number_float_t = typename BasicJsonType::number_float_t;
15791 
15792 public:
15793 /*!
15794 @brief create a binary writer
15795 
15796 @param[in] adapter output adapter to write to
15797 */
15798 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15799 {
15800 JSON_ASSERT(oa);
15801 }
15802 
15803 /*!
15804 @param[in] j JSON value to serialize
15805 @pre j.type() == value_t::object
15806 */
15807 void write_bson(const BasicJsonType& j)
15808 {
15809 switch (j.type())
15810 {
15811 case value_t::object:
15812 {
15813 write_bson_object(*j.m_data.m_value.object);
15814 break;
15815 }
15816 
15817 case value_t::null:
15818 case value_t::array:
15819 case value_t::string:
15820 case value_t::boolean:
15821 case value_t::number_integer:
15822 case value_t::number_unsigned:
15823 case value_t::number_float:
15824 case value_t::binary:
15825 case value_t::discarded:
15826 default:
15827 {
15828 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15829 }
15830 }
15831 }
15832 
15833 /*!
15834 @param[in] j JSON value to serialize
15835 */
15836 void write_cbor(const BasicJsonType& j)
15837 {
15838 switch (j.type())
15839 {
15840 case value_t::null:
15841 {
15842 oa->write_character(to_char_type(0xF6));
15843 break;
15844 }
15845 
15846 case value_t::boolean:
15847 {
15848 oa->write_character(j.m_data.m_value.boolean
15849 ? to_char_type(0xF5)
15850 : to_char_type(0xF4));
15851 break;
15852 }
15853 
15854 case value_t::number_integer:
15855 {
15856 if (j.m_data.m_value.number_integer >= 0)
15857 {
15858 // CBOR does not differentiate between positive signed
15859 // integers and unsigned integers. Therefore, we used the
15860 // code from the value_t::number_unsigned case here.
15861 if (j.m_data.m_value.number_integer <= 0x17)
15862 {
15863 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15864 }
15865 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15866 {
15867 oa->write_character(to_char_type(0x18));
15868 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15869 }
15870 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15871 {
15872 oa->write_character(to_char_type(0x19));
15873 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15874 }
15875 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15876 {
15877 oa->write_character(to_char_type(0x1A));
15878 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15879 }
15880 else
15881 {
15882 oa->write_character(to_char_type(0x1B));
15883 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15884 }
15885 }
15886 else
15887 {
15888 // The conversions below encode the sign in the first
15889 // byte, and the value is converted to a positive number.
15890 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15891 if (j.m_data.m_value.number_integer >= -24)
15892 {
15893 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15894 }
15895 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15896 {
15897 oa->write_character(to_char_type(0x38));
15898 write_number(static_cast<std::uint8_t>(positive_number));
15899 }
15900 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15901 {
15902 oa->write_character(to_char_type(0x39));
15903 write_number(static_cast<std::uint16_t>(positive_number));
15904 }
15905 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15906 {
15907 oa->write_character(to_char_type(0x3A));
15908 write_number(static_cast<std::uint32_t>(positive_number));
15909 }
15910 else
15911 {
15912 oa->write_character(to_char_type(0x3B));
15913 write_number(static_cast<std::uint64_t>(positive_number));
15914 }
15915 }
15916 break;
15917 }
15918 
15919 case value_t::number_unsigned:
15920 {
15921 if (j.m_data.m_value.number_unsigned <= 0x17)
15922 {
15923 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15924 }
15925 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15926 {
15927 oa->write_character(to_char_type(0x18));
15928 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15929 }
15930 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15931 {
15932 oa->write_character(to_char_type(0x19));
15933 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15934 }
15935 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15936 {
15937 oa->write_character(to_char_type(0x1A));
15938 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15939 }
15940 else
15941 {
15942 oa->write_character(to_char_type(0x1B));
15943 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15944 }
15945 break;
15946 }
15947 
15948 case value_t::number_float:
15949 {
15950 if (std::isnan(j.m_data.m_value.number_float))
15951 {
15952 // NaN is 0xf97e00 in CBOR
15953 oa->write_character(to_char_type(0xF9));
15954 oa->write_character(to_char_type(0x7E));
15955 oa->write_character(to_char_type(0x00));
15956 }
15957 else if (std::isinf(j.m_data.m_value.number_float))
15958 {
15959 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15960 oa->write_character(to_char_type(0xf9));
15961 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15962 oa->write_character(to_char_type(0x00));
15963 }
15964 else
15965 {
15966 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15967 }
15968 break;
15969 }
15970 
15971 case value_t::string:
15972 {
15973 // step 1: write control byte and the string length
15974 const auto N = j.m_data.m_value.string->size();
15975 if (N <= 0x17)
15976 {
15977 write_number(static_cast<std::uint8_t>(0x60 + N));
15978 }
15979 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15980 {
15981 oa->write_character(to_char_type(0x78));
15982 write_number(static_cast<std::uint8_t>(N));
15983 }
15984 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15985 {
15986 oa->write_character(to_char_type(0x79));
15987 write_number(static_cast<std::uint16_t>(N));
15988 }
15989 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15990 {
15991 oa->write_character(to_char_type(0x7A));
15992 write_number(static_cast<std::uint32_t>(N));
15993 }
15994 // LCOV_EXCL_START
15995 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15996 {
15997 oa->write_character(to_char_type(0x7B));
15998 write_number(static_cast<std::uint64_t>(N));
15999 }
16000 // LCOV_EXCL_STOP
16001 
16002 // step 2: write the string
16003 oa->write_characters(
16004 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16005 j.m_data.m_value.string->size());
16006 break;
16007 }
16008 
16009 case value_t::array:
16010 {
16011 // step 1: write control byte and the array size
16012 const auto N = j.m_data.m_value.array->size();
16013 if (N <= 0x17)
16014 {
16015 write_number(static_cast<std::uint8_t>(0x80 + N));
16016 }
16017 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16018 {
16019 oa->write_character(to_char_type(0x98));
16020 write_number(static_cast<std::uint8_t>(N));
16021 }
16022 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16023 {
16024 oa->write_character(to_char_type(0x99));
16025 write_number(static_cast<std::uint16_t>(N));
16026 }
16027 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16028 {
16029 oa->write_character(to_char_type(0x9A));
16030 write_number(static_cast<std::uint32_t>(N));
16031 }
16032 // LCOV_EXCL_START
16033 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16034 {
16035 oa->write_character(to_char_type(0x9B));
16036 write_number(static_cast<std::uint64_t>(N));
16037 }
16038 // LCOV_EXCL_STOP
16039 
16040 // step 2: write each element
16041 for (const auto& el : *j.m_data.m_value.array)
16042 {
16043 write_cbor(el);
16044 }
16045 break;
16046 }
16047 
16048 case value_t::binary:
16049 {
16050 if (j.m_data.m_value.binary->has_subtype())
16051 {
16052 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16053 {
16054 write_number(static_cast<std::uint8_t>(0xd8));
16055 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16056 }
16057 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16058 {
16059 write_number(static_cast<std::uint8_t>(0xd9));
16060 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16061 }
16062 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16063 {
16064 write_number(static_cast<std::uint8_t>(0xda));
16065 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16066 }
16067 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16068 {
16069 write_number(static_cast<std::uint8_t>(0xdb));
16070 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16071 }
16072 }
16073 
16074 // step 1: write control byte and the binary array size
16075 const auto N = j.m_data.m_value.binary->size();
16076 if (N <= 0x17)
16077 {
16078 write_number(static_cast<std::uint8_t>(0x40 + N));
16079 }
16080 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16081 {
16082 oa->write_character(to_char_type(0x58));
16083 write_number(static_cast<std::uint8_t>(N));
16084 }
16085 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16086 {
16087 oa->write_character(to_char_type(0x59));
16088 write_number(static_cast<std::uint16_t>(N));
16089 }
16090 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16091 {
16092 oa->write_character(to_char_type(0x5A));
16093 write_number(static_cast<std::uint32_t>(N));
16094 }
16095 // LCOV_EXCL_START
16096 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16097 {
16098 oa->write_character(to_char_type(0x5B));
16099 write_number(static_cast<std::uint64_t>(N));
16100 }
16101 // LCOV_EXCL_STOP
16102 
16103 // step 2: write each element
16104 oa->write_characters(
16105 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16106 N);
16107 
16108 break;
16109 }
16110 
16111 case value_t::object:
16112 {
16113 // step 1: write control byte and the object size
16114 const auto N = j.m_data.m_value.object->size();
16115 if (N <= 0x17)
16116 {
16117 write_number(static_cast<std::uint8_t>(0xA0 + N));
16118 }
16119 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16120 {
16121 oa->write_character(to_char_type(0xB8));
16122 write_number(static_cast<std::uint8_t>(N));
16123 }
16124 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16125 {
16126 oa->write_character(to_char_type(0xB9));
16127 write_number(static_cast<std::uint16_t>(N));
16128 }
16129 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16130 {
16131 oa->write_character(to_char_type(0xBA));
16132 write_number(static_cast<std::uint32_t>(N));
16133 }
16134 // LCOV_EXCL_START
16135 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16136 {
16137 oa->write_character(to_char_type(0xBB));
16138 write_number(static_cast<std::uint64_t>(N));
16139 }
16140 // LCOV_EXCL_STOP
16141 
16142 // step 2: write each element
16143 for (const auto& el : *j.m_data.m_value.object)
16144 {
16145 write_cbor(el.first);
16146 write_cbor(el.second);
16147 }
16148 break;
16149 }
16150 
16151 case value_t::discarded:
16152 default:
16153 break;
16154 }
16155 }
16156 
16157 /*!
16158 @param[in] j JSON value to serialize
16159 */
16160 void write_msgpack(const BasicJsonType& j)
16161 {
16162 switch (j.type())
16163 {
16164 case value_t::null: // nil
16165 {
16166 oa->write_character(to_char_type(0xC0));
16167 break;
16168 }
16169 
16170 case value_t::boolean: // true and false
16171 {
16172 oa->write_character(j.m_data.m_value.boolean
16173 ? to_char_type(0xC3)
16174 : to_char_type(0xC2));
16175 break;
16176 }
16177 
16178 case value_t::number_integer:
16179 {
16180 if (j.m_data.m_value.number_integer >= 0)
16181 {
16182 // MessagePack does not differentiate between positive
16183 // signed integers and unsigned integers. Therefore, we used
16184 // the code from the value_t::number_unsigned case here.
16185 if (j.m_data.m_value.number_unsigned < 128)
16186 {
16187 // positive fixnum
16188 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16189 }
16190 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16191 {
16192 // uint 8
16193 oa->write_character(to_char_type(0xCC));
16194 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16195 }
16196 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16197 {
16198 // uint 16
16199 oa->write_character(to_char_type(0xCD));
16200 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16201 }
16202 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16203 {
16204 // uint 32
16205 oa->write_character(to_char_type(0xCE));
16206 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16207 }
16208 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16209 {
16210 // uint 64
16211 oa->write_character(to_char_type(0xCF));
16212 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16213 }
16214 }
16215 else
16216 {
16217 if (j.m_data.m_value.number_integer >= -32)
16218 {
16219 // negative fixnum
16220 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16221 }
16222 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16223 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16224 {
16225 // int 8
16226 oa->write_character(to_char_type(0xD0));
16227 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16228 }
16229 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16230 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16231 {
16232 // int 16
16233 oa->write_character(to_char_type(0xD1));
16234 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16235 }
16236 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16237 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16238 {
16239 // int 32
16240 oa->write_character(to_char_type(0xD2));
16241 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16242 }
16243 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16244 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16245 {
16246 // int 64
16247 oa->write_character(to_char_type(0xD3));
16248 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16249 }
16250 }
16251 break;
16252 }
16253 
16254 case value_t::number_unsigned:
16255 {
16256 if (j.m_data.m_value.number_unsigned < 128)
16257 {
16258 // positive fixnum
16259 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16260 }
16261 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16262 {
16263 // uint 8
16264 oa->write_character(to_char_type(0xCC));
16265 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16266 }
16267 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16268 {
16269 // uint 16
16270 oa->write_character(to_char_type(0xCD));
16271 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16272 }
16273 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16274 {
16275 // uint 32
16276 oa->write_character(to_char_type(0xCE));
16277 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16278 }
16279 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16280 {
16281 // uint 64
16282 oa->write_character(to_char_type(0xCF));
16283 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16284 }
16285 break;
16286 }
16287 
16288 case value_t::number_float:
16289 {
16290 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16291 break;
16292 }
16293 
16294 case value_t::string:
16295 {
16296 // step 1: write control byte and the string length
16297 const auto N = j.m_data.m_value.string->size();
16298 if (N <= 31)
16299 {
16300 // fixstr
16301 write_number(static_cast<std::uint8_t>(0xA0 | N));
16302 }
16303 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16304 {
16305 // str 8
16306 oa->write_character(to_char_type(0xD9));
16307 write_number(static_cast<std::uint8_t>(N));
16308 }
16309 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16310 {
16311 // str 16
16312 oa->write_character(to_char_type(0xDA));
16313 write_number(static_cast<std::uint16_t>(N));
16314 }
16315 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16316 {
16317 // str 32
16318 oa->write_character(to_char_type(0xDB));
16319 write_number(static_cast<std::uint32_t>(N));
16320 }
16321 
16322 // step 2: write the string
16323 oa->write_characters(
16324 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16325 j.m_data.m_value.string->size());
16326 break;
16327 }
16328 
16329 case value_t::array:
16330 {
16331 // step 1: write control byte and the array size
16332 const auto N = j.m_data.m_value.array->size();
16333 if (N <= 15)
16334 {
16335 // fixarray
16336 write_number(static_cast<std::uint8_t>(0x90 | N));
16337 }
16338 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16339 {
16340 // array 16
16341 oa->write_character(to_char_type(0xDC));
16342 write_number(static_cast<std::uint16_t>(N));
16343 }
16344 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16345 {
16346 // array 32
16347 oa->write_character(to_char_type(0xDD));
16348 write_number(static_cast<std::uint32_t>(N));
16349 }
16350 
16351 // step 2: write each element
16352 for (const auto& el : *j.m_data.m_value.array)
16353 {
16354 write_msgpack(el);
16355 }
16356 break;
16357 }
16358 
16359 case value_t::binary:
16360 {
16361 // step 0: determine if the binary type has a set subtype to
16362 // determine whether to use the ext or fixext types
16363 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16364 
16365 // step 1: write control byte and the byte string length
16366 const auto N = j.m_data.m_value.binary->size();
16367 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16368 {
16369 std::uint8_t output_type{};
16370 bool fixed = true;
16371 if (use_ext)
16372 {
16373 switch (N)
16374 {
16375 case 1:
16376 output_type = 0xD4; // fixext 1
16377 break;
16378 case 2:
16379 output_type = 0xD5; // fixext 2
16380 break;
16381 case 4:
16382 output_type = 0xD6; // fixext 4
16383 break;
16384 case 8:
16385 output_type = 0xD7; // fixext 8
16386 break;
16387 case 16:
16388 output_type = 0xD8; // fixext 16
16389 break;
16390 default:
16391 output_type = 0xC7; // ext 8
16392 fixed = false;
16393 break;
16394 }
16395 
16396 }
16397 else
16398 {
16399 output_type = 0xC4; // bin 8
16400 fixed = false;
16401 }
16402 
16403 oa->write_character(to_char_type(output_type));
16404 if (!fixed)
16405 {
16406 write_number(static_cast<std::uint8_t>(N));
16407 }
16408 }
16409 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16410 {
16411 const std::uint8_t output_type = use_ext
16412 ? 0xC8 // ext 16
16413 : 0xC5; // bin 16
16414 
16415 oa->write_character(to_char_type(output_type));
16416 write_number(static_cast<std::uint16_t>(N));
16417 }
16418 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16419 {
16420 const std::uint8_t output_type = use_ext
16421 ? 0xC9 // ext 32
16422 : 0xC6; // bin 32
16423 
16424 oa->write_character(to_char_type(output_type));
16425 write_number(static_cast<std::uint32_t>(N));
16426 }
16427 
16428 // step 1.5: if this is an ext type, write the subtype
16429 if (use_ext)
16430 {
16431 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16432 }
16433 
16434 // step 2: write the byte string
16435 oa->write_characters(
16436 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16437 N);
16438 
16439 break;
16440 }
16441 
16442 case value_t::object:
16443 {
16444 // step 1: write control byte and the object size
16445 const auto N = j.m_data.m_value.object->size();
16446 if (N <= 15)
16447 {
16448 // fixmap
16449 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16450 }
16451 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16452 {
16453 // map 16
16454 oa->write_character(to_char_type(0xDE));
16455 write_number(static_cast<std::uint16_t>(N));
16456 }
16457 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16458 {
16459 // map 32
16460 oa->write_character(to_char_type(0xDF));
16461 write_number(static_cast<std::uint32_t>(N));
16462 }
16463 
16464 // step 2: write each element
16465 for (const auto& el : *j.m_data.m_value.object)
16466 {
16467 write_msgpack(el.first);
16468 write_msgpack(el.second);
16469 }
16470 break;
16471 }
16472 
16473 case value_t::discarded:
16474 default:
16475 break;
16476 }
16477 }
16478 
16479 /*!
16480 @param[in] j JSON value to serialize
16481 @param[in] use_count whether to use '#' prefixes (optimized format)
16482 @param[in] use_type whether to use '$' prefixes (optimized format)
16483 @param[in] add_prefix whether prefixes need to be used for this value
16484 @param[in] use_bjdata whether write in BJData format, default is false
16485 @param[in] bjdata_version which BJData version to use, default is draft2
16486 */
16487 void write_ubjson(const BasicJsonType& j, const bool use_count,
16488 const bool use_type, const bool add_prefix = true,
16489 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16490 {
16491 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16492 
16493 switch (j.type())
16494 {
16495 case value_t::null:
16496 {
16497 if (add_prefix)
16498 {
16499 oa->write_character(to_char_type('Z'));
16500 }
16501 break;
16502 }
16503 
16504 case value_t::boolean:
16505 {
16506 if (add_prefix)
16507 {
16508 oa->write_character(j.m_data.m_value.boolean
16509 ? to_char_type('T')
16510 : to_char_type('F'));
16511 }
16512 break;
16513 }
16514 
16515 case value_t::number_integer:
16516 {
16517 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16518 break;
16519 }
16520 
16521 case value_t::number_unsigned:
16522 {
16523 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16524 break;
16525 }
16526 
16527 case value_t::number_float:
16528 {
16529 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16530 break;
16531 }
16532 
16533 case value_t::string:
16534 {
16535 if (add_prefix)
16536 {
16537 oa->write_character(to_char_type('S'));
16538 }
16539 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16540 oa->write_characters(
16541 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16542 j.m_data.m_value.string->size());
16543 break;
16544 }
16545 
16546 case value_t::array:
16547 {
16548 if (add_prefix)
16549 {
16550 oa->write_character(to_char_type('['));
16551 }
16552 
16553 bool prefix_required = true;
16554 if (use_type && !j.m_data.m_value.array->empty())
16555 {
16556 JSON_ASSERT(use_count);
16557 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16558 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16559 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16560 {
16561 return ubjson_prefix(v, use_bjdata) == first_prefix;
16562 });
16563 
16564 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16565 
16566 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16567 {
16568 prefix_required = false;
16569 oa->write_character(to_char_type('$'));
16570 oa->write_character(first_prefix);
16571 }
16572 }
16573 
16574 if (use_count)
16575 {
16576 oa->write_character(to_char_type('#'));
16577 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16578 }
16579 
16580 for (const auto& el : *j.m_data.m_value.array)
16581 {
16582 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16583 }
16584 
16585 if (!use_count)
16586 {
16587 oa->write_character(to_char_type(']'));
16588 }
16589 
16590 break;
16591 }
16592 
16593 case value_t::binary:
16594 {
16595 if (add_prefix)
16596 {
16597 oa->write_character(to_char_type('['));
16598 }
16599 
16600 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16601 {
16602 JSON_ASSERT(use_count);
16603 oa->write_character(to_char_type('$'));
16604 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16605 }
16606 
16607 if (use_count)
16608 {
16609 oa->write_character(to_char_type('#'));
16610 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16611 }
16612 
16613 if (use_type)
16614 {
16615 oa->write_characters(
16616 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16617 j.m_data.m_value.binary->size());
16618 }
16619 else
16620 {
16621 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16622 {
16623 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16624 oa->write_character(j.m_data.m_value.binary->data()[i]);
16625 }
16626 }
16627 
16628 if (!use_count)
16629 {
16630 oa->write_character(to_char_type(']'));
16631 }
16632 
16633 break;
16634 }
16635 
16636 case value_t::object:
16637 {
16638 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())
16639 {
16640 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16641 {
16642 break;
16643 }
16644 }
16645 
16646 if (add_prefix)
16647 {
16648 oa->write_character(to_char_type('{'));
16649 }
16650 
16651 bool prefix_required = true;
16652 if (use_type && !j.m_data.m_value.object->empty())
16653 {
16654 JSON_ASSERT(use_count);
16655 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16656 const bool same_prefix = std::all_of(j.begin(), j.end(),
16657 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16658 {
16659 return ubjson_prefix(v, use_bjdata) == first_prefix;
16660 });
16661 
16662 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16663 
16664 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16665 {
16666 prefix_required = false;
16667 oa->write_character(to_char_type('$'));
16668 oa->write_character(first_prefix);
16669 }
16670 }
16671 
16672 if (use_count)
16673 {
16674 oa->write_character(to_char_type('#'));
16675 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16676 }
16677 
16678 for (const auto& el : *j.m_data.m_value.object)
16679 {
16680 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16681 oa->write_characters(
16682 reinterpret_cast<const CharType*>(el.first.c_str()),
16683 el.first.size());
16684 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16685 }
16686 
16687 if (!use_count)
16688 {
16689 oa->write_character(to_char_type('}'));
16690 }
16691 
16692 break;
16693 }
16694 
16695 case value_t::discarded:
16696 default:
16697 break;
16698 }
16699 }
16700 
16701 private:
16702 //////////
16703 // BSON //
16704 //////////
16705 
16706 /*!
16707 @return The size of a BSON document entry header, including the id marker
16708 and the entry name size (and its null-terminator).
16709 */
16710 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16711 {
16712 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16713 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16714 {
16715 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16716 static_cast<void>(j);
16717 }
16718 
16719 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16720 }
16721 
16722 /*!
16723 @brief Writes the given @a element_type and @a name to the output adapter
16724 */
16725 void write_bson_entry_header(const string_t& name,
16726 const std::uint8_t element_type)
16727 {
16728 oa->write_character(to_char_type(element_type)); // boolean
16729 oa->write_characters(
16730 reinterpret_cast<const CharType*>(name.c_str()),
16731 name.size() + 1u);
16732 }
16733 
16734 /*!
16735 @brief Writes a BSON element with key @a name and boolean value @a value
16736 */
16737 void write_bson_boolean(const string_t& name,
16738 const bool value)
16739 {
16740 write_bson_entry_header(name, 0x08);
16741 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16742 }
16743 
16744 /*!
16745 @brief Writes a BSON element with key @a name and double value @a value
16746 */
16747 void write_bson_double(const string_t& name,
16748 const double value)
16749 {
16750 write_bson_entry_header(name, 0x01);
16751 write_number<double>(value, true);
16752 }
16753 
16754 /*!
16755 @return The size of the BSON-encoded string in @a value
16756 */
16757 static std::size_t calc_bson_string_size(const string_t& value)
16758 {
16759 return sizeof(std::int32_t) + value.size() + 1ul;
16760 }
16761 
16762 /*!
16763 @brief Writes a BSON element with key @a name and string value @a value
16764 */
16765 void write_bson_string(const string_t& name,
16766 const string_t& value)
16767 {
16768 write_bson_entry_header(name, 0x02);
16769 
16770 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16771 oa->write_characters(
16772 reinterpret_cast<const CharType*>(value.c_str()),
16773 value.size() + 1);
16774 }
16775 
16776 /*!
16777 @brief Writes a BSON element with key @a name and null value
16778 */
16779 void write_bson_null(const string_t& name)
16780 {
16781 write_bson_entry_header(name, 0x0A);
16782 }
16783 
16784 /*!
16785 @return The size of the BSON-encoded integer @a value
16786 */
16787 static std::size_t calc_bson_integer_size(const std::int64_t value)
16788 {
16789 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16790 ? sizeof(std::int32_t)
16791 : sizeof(std::int64_t);
16792 }
16793 
16794 /*!
16795 @brief Writes a BSON element with key @a name and integer @a value
16796 */
16797 void write_bson_integer(const string_t& name,
16798 const std::int64_t value)
16799 {
16800 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16801 {
16802 write_bson_entry_header(name, 0x10); // int32
16803 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16804 }
16805 else
16806 {
16807 write_bson_entry_header(name, 0x12); // int64
16808 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16809 }
16810 }
16811 
16812 /*!
16813 @return The size of the BSON-encoded unsigned integer in @a j
16814 */
16815 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16816 {
16817 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16818 ? sizeof(std::int32_t)
16819 : sizeof(std::int64_t);
16820 }
16821 
16822 /*!
16823 @brief Writes a BSON element with key @a name and unsigned @a value
16824 */
16825 void write_bson_unsigned(const string_t& name,
16826 const BasicJsonType& j)
16827 {
16828 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16829 {
16830 write_bson_entry_header(name, 0x10 /* int32 */);
16831 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16832 }
16833 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16834 {
16835 write_bson_entry_header(name, 0x12 /* int64 */);
16836 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16837 }
16838 else
16839 {
16840 write_bson_entry_header(name, 0x11 /* uint64 */);
16841 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16842 }
16843 }
16844 
16845 /*!
16846 @brief Writes a BSON element with key @a name and object @a value
16847 */
16848 void write_bson_object_entry(const string_t& name,
16849 const typename BasicJsonType::object_t& value)
16850 {
16851 write_bson_entry_header(name, 0x03); // object
16852 write_bson_object(value);
16853 }
16854 
16855 /*!
16856 @return The size of the BSON-encoded array @a value
16857 */
16858 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16859 {
16860 std::size_t array_index = 0ul;
16861 
16862 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)
16863 {
16864 return result + calc_bson_element_size(std::to_string(array_index++), el);
16865 });
16866 
16867 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16868 }
16869 
16870 /*!
16871 @return The size of the BSON-encoded binary array @a value
16872 */
16873 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16874 {
16875 return sizeof(std::int32_t) + value.size() + 1ul;
16876 }
16877 
16878 /*!
16879 @brief Writes a BSON element with key @a name and array @a value
16880 */
16881 void write_bson_array(const string_t& name,
16882 const typename BasicJsonType::array_t& value)
16883 {
16884 write_bson_entry_header(name, 0x04); // array
16885 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16886 
16887 std::size_t array_index = 0ul;
16888 
16889 for (const auto& el : value)
16890 {
16891 write_bson_element(std::to_string(array_index++), el);
16892 }
16893 
16894 oa->write_character(to_char_type(0x00));
16895 }
16896 
16897 /*!
16898 @brief Writes a BSON element with key @a name and binary value @a value
16899 */
16900 void write_bson_binary(const string_t& name,
16901 const binary_t& value)
16902 {
16903 write_bson_entry_header(name, 0x05);
16904 
16905 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16906 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16907 
16908 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16909 }
16910 
16911 /*!
16912 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16913 @return The calculated size for the BSON document entry for @a j with the given @a name.
16914 */
16915 static std::size_t calc_bson_element_size(const string_t& name,
16916 const BasicJsonType& j)
16917 {
16918 const auto header_size = calc_bson_entry_header_size(name, j);
16919 switch (j.type())
16920 {
16921 case value_t::object:
16922 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16923 
16924 case value_t::array:
16925 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16926 
16927 case value_t::binary:
16928 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16929 
16930 case value_t::boolean:
16931 return header_size + 1ul;
16932 
16933 case value_t::number_float:
16934 return header_size + 8ul;
16935 
16936 case value_t::number_integer:
16937 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16938 
16939 case value_t::number_unsigned:
16940 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16941 
16942 case value_t::string:
16943 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16944 
16945 case value_t::null:
16946 return header_size + 0ul;
16947 
16948 // LCOV_EXCL_START
16949 case value_t::discarded:
16950 default:
16951 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16952 return 0ul;
16953 // LCOV_EXCL_STOP
16954 }
16955 }
16956 
16957 /*!
16958 @brief Serializes the JSON value @a j to BSON and associates it with the
16959 key @a name.
16960 @param name The name to associate with the JSON entity @a j within the
16961 current BSON document
16962 */
16963 void write_bson_element(const string_t& name,
16964 const BasicJsonType& j)
16965 {
16966 switch (j.type())
16967 {
16968 case value_t::object:
16969 return write_bson_object_entry(name, *j.m_data.m_value.object);
16970 
16971 case value_t::array:
16972 return write_bson_array(name, *j.m_data.m_value.array);
16973 
16974 case value_t::binary:
16975 return write_bson_binary(name, *j.m_data.m_value.binary);
16976 
16977 case value_t::boolean:
16978 return write_bson_boolean(name, j.m_data.m_value.boolean);
16979 
16980 case value_t::number_float:
16981 return write_bson_double(name, j.m_data.m_value.number_float);
16982 
16983 case value_t::number_integer:
16984 return write_bson_integer(name, j.m_data.m_value.number_integer);
16985 
16986 case value_t::number_unsigned:
16987 return write_bson_unsigned(name, j);
16988 
16989 case value_t::string:
16990 return write_bson_string(name, *j.m_data.m_value.string);
16991 
16992 case value_t::null:
16993 return write_bson_null(name);
16994 
16995 // LCOV_EXCL_START
16996 case value_t::discarded:
16997 default:
16998 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16999 return;
17000 // LCOV_EXCL_STOP
17001 }
17002 }
17003 
17004 /*!
17005 @brief Calculates the size of the BSON serialization of the given
17006 JSON-object @a j.
17007 @param[in] value JSON value to serialize
17008 @pre value.type() == value_t::object
17009 */
17010 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17011 {
17012 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17013 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17014 {
17015 return result += calc_bson_element_size(el.first, el.second);
17016 });
17017 
17018 return sizeof(std::int32_t) + document_size + 1ul;
17019 }
17020 
17021 /*!
17022 @param[in] value JSON value to serialize
17023 @pre value.type() == value_t::object
17024 */
17025 void write_bson_object(const typename BasicJsonType::object_t& value)
17026 {
17027 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17028 
17029 for (const auto& el : value)
17030 {
17031 write_bson_element(el.first, el.second);
17032 }
17033 
17034 oa->write_character(to_char_type(0x00));
17035 }
17036 
17037 //////////
17038 // CBOR //
17039 //////////
17040 
17041 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17042 {
17043 return to_char_type(0xFA); // Single-Precision Float
17044 }
17045 
17046 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17047 {
17048 return to_char_type(0xFB); // Double-Precision Float
17049 }
17050 
17051 /////////////
17052 // MsgPack //
17053 /////////////
17054 
17055 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17056 {
17057 return to_char_type(0xCA); // float 32
17058 }
17059 
17060 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17061 {
17062 return to_char_type(0xCB); // float 64
17063 }
17064 
17065 ////////////
17066 // UBJSON //
17067 ////////////
17068 
17069 // UBJSON: write number (floating point)
17070 template<typename NumberType, typename std::enable_if<
17071 std::is_floating_point<NumberType>::value, int>::type = 0>
17072 void write_number_with_ubjson_prefix(const NumberType n,
17073 const bool add_prefix,
17074 const bool use_bjdata)
17075 {
17076 if (add_prefix)
17077 {
17078 oa->write_character(get_ubjson_float_prefix(n));
17079 }
17080 write_number(n, use_bjdata);
17081 }
17082 
17083 // UBJSON: write number (unsigned integer)
17084 template<typename NumberType, typename std::enable_if<
17085 std::is_unsigned<NumberType>::value, int>::type = 0>
17086 void write_number_with_ubjson_prefix(const NumberType n,
17087 const bool add_prefix,
17088 const bool use_bjdata)
17089 {
17090 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17091 {
17092 if (add_prefix)
17093 {
17094 oa->write_character(to_char_type('i')); // int8
17095 }
17096 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17097 }
17098 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17099 {
17100 if (add_prefix)
17101 {
17102 oa->write_character(to_char_type('U')); // uint8
17103 }
17104 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17105 }
17106 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17107 {
17108 if (add_prefix)
17109 {
17110 oa->write_character(to_char_type('I')); // int16
17111 }
17112 write_number(static_cast<std::int16_t>(n), use_bjdata);
17113 }
17114 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17115 {
17116 if (add_prefix)
17117 {
17118 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17119 }
17120 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17121 }
17122 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17123 {
17124 if (add_prefix)
17125 {
17126 oa->write_character(to_char_type('l')); // int32
17127 }
17128 write_number(static_cast<std::int32_t>(n), use_bjdata);
17129 }
17130 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17131 {
17132 if (add_prefix)
17133 {
17134 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17135 }
17136 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17137 }
17138 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17139 {
17140 if (add_prefix)
17141 {
17142 oa->write_character(to_char_type('L')); // int64
17143 }
17144 write_number(static_cast<std::int64_t>(n), use_bjdata);
17145 }
17146 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17147 {
17148 if (add_prefix)
17149 {
17150 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17151 }
17152 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17153 }
17154 else
17155 {
17156 if (add_prefix)
17157 {
17158 oa->write_character(to_char_type('H')); // high-precision number
17159 }
17160 
17161 const auto number = BasicJsonType(n).dump();
17162 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17163 for (std::size_t i = 0; i < number.size(); ++i)
17164 {
17165 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17166 }
17167 }
17168 }
17169 
17170 // UBJSON: write number (signed integer)
17171 template < typename NumberType, typename std::enable_if <
17172 std::is_signed<NumberType>::value&&
17173 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17174 void write_number_with_ubjson_prefix(const NumberType n,
17175 const bool add_prefix,
17176 const bool use_bjdata)
17177 {
17178 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17179 {
17180 if (add_prefix)
17181 {
17182 oa->write_character(to_char_type('i')); // int8
17183 }
17184 write_number(static_cast<std::int8_t>(n), use_bjdata);
17185 }
17186 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)()))
17187 {
17188 if (add_prefix)
17189 {
17190 oa->write_character(to_char_type('U')); // uint8
17191 }
17192 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17193 }
17194 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17195 {
17196 if (add_prefix)
17197 {
17198 oa->write_character(to_char_type('I')); // int16
17199 }
17200 write_number(static_cast<std::int16_t>(n), use_bjdata);
17201 }
17202 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)())))
17203 {
17204 if (add_prefix)
17205 {
17206 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17207 }
17208 write_number(static_cast<uint16_t>(n), use_bjdata);
17209 }
17210 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17211 {
17212 if (add_prefix)
17213 {
17214 oa->write_character(to_char_type('l')); // int32
17215 }
17216 write_number(static_cast<std::int32_t>(n), use_bjdata);
17217 }
17218 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)())))
17219 {
17220 if (add_prefix)
17221 {
17222 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17223 }
17224 write_number(static_cast<uint32_t>(n), use_bjdata);
17225 }
17226 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17227 {
17228 if (add_prefix)
17229 {
17230 oa->write_character(to_char_type('L')); // int64
17231 }
17232 write_number(static_cast<std::int64_t>(n), use_bjdata);
17233 }
17234 // LCOV_EXCL_START
17235 else
17236 {
17237 if (add_prefix)
17238 {
17239 oa->write_character(to_char_type('H')); // high-precision number
17240 }
17241 
17242 const auto number = BasicJsonType(n).dump();
17243 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17244 for (std::size_t i = 0; i < number.size(); ++i)
17245 {
17246 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17247 }
17248 }
17249 // LCOV_EXCL_STOP
17250 }
17251 
17252 /*!
17253 @brief determine the type prefix of container values
17254 */
17255 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17256 {
17257 switch (j.type())
17258 {
17259 case value_t::null:
17260 return 'Z';
17261 
17262 case value_t::boolean:
17263 return j.m_data.m_value.boolean ? 'T' : 'F';
17264 
17265 case value_t::number_integer:
17266 {
17267 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)())
17268 {
17269 return 'i';
17270 }
17271 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)())
17272 {
17273 return 'U';
17274 }
17275 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)())
17276 {
17277 return 'I';
17278 }
17279 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)()))
17280 {
17281 return 'u';
17282 }
17283 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)())
17284 {
17285 return 'l';
17286 }
17287 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)()))
17288 {
17289 return 'm';
17290 }
17291 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)())
17292 {
17293 return 'L';
17294 }
17295 // anything else is treated as high-precision number
17296 return 'H'; // LCOV_EXCL_LINE
17297 }
17298 
17299 case value_t::number_unsigned:
17300 {
17301 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17302 {
17303 return 'i';
17304 }
17305 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17306 {
17307 return 'U';
17308 }
17309 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17310 {
17311 return 'I';
17312 }
17313 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17314 {
17315 return 'u';
17316 }
17317 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17318 {
17319 return 'l';
17320 }
17321 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17322 {
17323 return 'm';
17324 }
17325 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17326 {
17327 return 'L';
17328 }
17329 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17330 {
17331 return 'M';
17332 }
17333 // anything else is treated as high-precision number
17334 return 'H'; // LCOV_EXCL_LINE
17335 }
17336 
17337 case value_t::number_float:
17338 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17339 
17340 case value_t::string:
17341 return 'S';
17342 
17343 case value_t::array: // fallthrough
17344 case value_t::binary:
17345 return '[';
17346 
17347 case value_t::object:
17348 return '{';
17349 
17350 case value_t::discarded:
17351 default: // discarded values
17352 return 'N';
17353 }
17354 }
17355 
17356 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17357 {
17358 return 'd'; // float 32
17359 }
17360 
17361 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17362 {
17363 return 'D'; // float 64
17364 }
17365 
17366 /*!
17367 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
17368 */
17369 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17370 {
17371 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17372 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17373 {"char", 'C'}, {"byte", 'B'}
17374 };
17375 
17376 string_t key = "_ArrayType_";
17377 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17378 if (it == bjdtype.end())
17379 {
17380 return true;
17381 }
17382 CharType dtype = it->second;
17383 
17384 key = "_ArraySize_";
17385 std::size_t len = (value.at(key).empty() ? 0 : 1);
17386 for (const auto& el : value.at(key))
17387 {
17388 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17389 }
17390 
17391 key = "_ArrayData_";
17392 if (value.at(key).size() != len)
17393 {
17394 return true;
17395 }
17396 
17397 oa->write_character('[');
17398 oa->write_character('$');
17399 oa->write_character(dtype);
17400 oa->write_character('#');
17401 
17402 key = "_ArraySize_";
17403 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17404 
17405 key = "_ArrayData_";
17406 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17407 {
17408 for (const auto& el : value.at(key))
17409 {
17410 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17411 }
17412 }
17413 else if (dtype == 'i')
17414 {
17415 for (const auto& el : value.at(key))
17416 {
17417 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17418 }
17419 }
17420 else if (dtype == 'u')
17421 {
17422 for (const auto& el : value.at(key))
17423 {
17424 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17425 }
17426 }
17427 else if (dtype == 'I')
17428 {
17429 for (const auto& el : value.at(key))
17430 {
17431 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17432 }
17433 }
17434 else if (dtype == 'm')
17435 {
17436 for (const auto& el : value.at(key))
17437 {
17438 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17439 }
17440 }
17441 else if (dtype == 'l')
17442 {
17443 for (const auto& el : value.at(key))
17444 {
17445 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17446 }
17447 }
17448 else if (dtype == 'M')
17449 {
17450 for (const auto& el : value.at(key))
17451 {
17452 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17453 }
17454 }
17455 else if (dtype == 'L')
17456 {
17457 for (const auto& el : value.at(key))
17458 {
17459 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17460 }
17461 }
17462 else if (dtype == 'd')
17463 {
17464 for (const auto& el : value.at(key))
17465 {
17466 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17467 }
17468 }
17469 else if (dtype == 'D')
17470 {
17471 for (const auto& el : value.at(key))
17472 {
17473 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17474 }
17475 }
17476 return false;
17477 }
17478 
17479 ///////////////////////
17480 // Utility functions //
17481 ///////////////////////
17482 
17483 /*
17484 @brief write a number to output input
17485 @param[in] n number of type @a NumberType
17486 @param[in] OutputIsLittleEndian Set to true if output data is
17487 required to be little endian
17488 @tparam NumberType the type of the number
17489 
17490 @note This function needs to respect the system's endianness, because bytes
17491 in CBOR, MessagePack, and UBJSON are stored in network order (big
17492 endian) and therefore need reordering on little endian systems.
17493 On the other hand, BSON and BJData use little endian and should reorder
17494 on big endian systems.
17495 */
17496 template<typename NumberType>
17497 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17498 {
17499 // step 1: write number to array of length NumberType
17500 std::array<CharType, sizeof(NumberType)> vec{};
17501 std::memcpy(vec.data(), &n, sizeof(NumberType));
17502 
17503 // step 2: write array to output (with possible reordering)
17504 if (is_little_endian != OutputIsLittleEndian)
17505 {
17506 // reverse byte order prior to conversion if necessary
17507 std::reverse(vec.begin(), vec.end());
17508 }
17509 
17510 oa->write_characters(vec.data(), sizeof(NumberType));
17511 }
17512 
17513 void write_compact_float(const number_float_t n, detail::input_format_t format)
17514 {
17515#ifdef __GNUC__
17516#pragma GCC diagnostic push
17517#pragma GCC diagnostic ignored "-Wfloat-equal"
17518#endif
17519 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17520 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17521 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17522 {
17523 oa->write_character(format == detail::input_format_t::cbor
17524 ? get_cbor_float_prefix(static_cast<float>(n))
17525 : get_msgpack_float_prefix(static_cast<float>(n)));
17526 write_number(static_cast<float>(n));
17527 }
17528 else
17529 {
17530 oa->write_character(format == detail::input_format_t::cbor
17531 ? get_cbor_float_prefix(n)
17532 : get_msgpack_float_prefix(n));
17533 write_number(n);
17534 }
17535#ifdef __GNUC__
17536#pragma GCC diagnostic pop
17537#endif
17538 }
17539 
17540 public:
17541 // The following to_char_type functions are implement the conversion
17542 // between uint8_t and CharType. In case CharType is not unsigned,
17543 // such a conversion is required to allow values greater than 128.
17544 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17545 template < typename C = CharType,
17546 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17547 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17548 {
17549 return *reinterpret_cast<char*>(&x);
17550 }
17551 
17552 template < typename C = CharType,
17553 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17554 static CharType to_char_type(std::uint8_t x) noexcept
17555 {
17556 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17557 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17558 CharType result;
17559 std::memcpy(&result, &x, sizeof(x));
17560 return result;
17561 }
17562 
17563 template<typename C = CharType,
17564 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17565 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17566 {
17567 return x;
17568 }
17569 
17570 template < typename InputCharType, typename C = CharType,
17571 enable_if_t <
17572 std::is_signed<C>::value &&
17573 std::is_signed<char>::value &&
17574 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17575 > * = nullptr >
17576 static constexpr CharType to_char_type(InputCharType x) noexcept
17577 {
17578 return x;
17579 }
17580 
17581 private:
17582 /// whether we can assume little endianness
17583 const bool is_little_endian = little_endianness();
17584 
17585 /// the output
17586 output_adapter_t<CharType> oa = nullptr;
17587};
17588 
17589} // namespace detail
17590NLOHMANN_JSON_NAMESPACE_END
17591 
17592// #include <nlohmann/detail/output/output_adapters.hpp>
17593 
17594// #include <nlohmann/detail/output/serializer.hpp>
17595// __ _____ _____ _____
17596// __| | __| | | | JSON for Modern C++
17597// | | |__ | | | | | | version 3.12.0
17598// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17599//
17600// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17601// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17602// SPDX-License-Identifier: MIT
17603 
17604 
17605 
17606#include <algorithm> // reverse, remove, fill, find, none_of
17607#include <array> // array
17608#include <clocale> // localeconv, lconv
17609#include <cmath> // labs, isfinite, isnan, signbit
17610#include <cstddef> // size_t, ptrdiff_t
17611#include <cstdint> // uint8_t
17612#include <cstdio> // snprintf
17613#include <limits> // numeric_limits
17614#include <string> // string, char_traits
17615#include <iomanip> // setfill, setw
17616#include <type_traits> // is_same
17617#include <utility> // move
17618 
17619// #include <nlohmann/detail/conversions/to_chars.hpp>
17620// __ _____ _____ _____
17621// __| | __| | | | JSON for Modern C++
17622// | | |__ | | | | | | version 3.12.0
17623// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17624//
17625// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17626// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17627// SPDX-License-Identifier: MIT
17628 
17629 
17630 
17631#include <array> // array
17632#include <cmath> // signbit, isfinite
17633#include <cstdint> // intN_t, uintN_t
17634#include <cstring> // memcpy, memmove
17635#include <limits> // numeric_limits
17636#include <type_traits> // conditional
17637 
17638// #include <nlohmann/detail/macro_scope.hpp>
17639 
17640 
17641NLOHMANN_JSON_NAMESPACE_BEGIN
17642namespace detail
17643{
17644 
17645/*!
17646@brief implements the Grisu2 algorithm for binary to decimal floating-point
17647conversion.
17648 
17649This implementation is a slightly modified version of the reference
17650implementation which may be obtained from
17651http://florian.loitsch.com/publications (bench.tar.gz).
17652 
17653The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
17654 
17655For a detailed description of the algorithm see:
17656 
17657[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
17658 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
17659 Language Design and Implementation, PLDI 2010
17660[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
17661 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
17662 Design and Implementation, PLDI 1996
17663*/
17664namespace dtoa_impl
17665{
17666 
17667template<typename Target, typename Source>
17668Target reinterpret_bits(const Source source)
17669{
17670 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17671 
17672 Target target;
17673 std::memcpy(&target, &source, sizeof(Source));
17674 return target;
17675}
17676 
17677struct diyfp // f * 2^e
17678{
17679 static constexpr int kPrecision = 64; // = q
17680 
17681 std::uint64_t f = 0;
17682 int e = 0;
17683 
17684 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17685 
17686 /*!
17687 @brief returns x - y
17688 @pre x.e == y.e and x.f >= y.f
17689 */
17690 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17691 {
17692 JSON_ASSERT(x.e == y.e);
17693 JSON_ASSERT(x.f >= y.f);
17694 
17695 return {x.f - y.f, x.e};
17696 }
17697 
17698 /*!
17699 @brief returns x * y
17700 @note The result is rounded. (Only the upper q bits are returned.)
17701 */
17702 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17703 {
17704 static_assert(kPrecision == 64, "internal error");
17705 
17706 // Computes:
17707 // f = round((x.f * y.f) / 2^q)
17708 // e = x.e + y.e + q
17709 
17710 // Emulate the 64-bit * 64-bit multiplication:
17711 //
17712 // p = u * v
17713 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17714 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17715 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17716 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17717 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17718 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17719 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17720 //
17721 // (Since Q might be larger than 2^32 - 1)
17722 //
17723 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17724 //
17725 // (Q_hi + H does not overflow a 64-bit int)
17726 //
17727 // = p_lo + 2^64 p_hi
17728 
17729 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17730 const std::uint64_t u_hi = x.f >> 32u;
17731 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17732 const std::uint64_t v_hi = y.f >> 32u;
17733 
17734 const std::uint64_t p0 = u_lo * v_lo;
17735 const std::uint64_t p1 = u_lo * v_hi;
17736 const std::uint64_t p2 = u_hi * v_lo;
17737 const std::uint64_t p3 = u_hi * v_hi;
17738 
17739 const std::uint64_t p0_hi = p0 >> 32u;
17740 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17741 const std::uint64_t p1_hi = p1 >> 32u;
17742 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17743 const std::uint64_t p2_hi = p2 >> 32u;
17744 
17745 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17746 
17747 // The full product might now be computed as
17748 //
17749 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17750 // p_lo = p0_lo + (Q << 32)
17751 //
17752 // But in this particular case here, the full p_lo is not required.
17753 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17754 // Q_hi + 1 does not overflow).
17755 
17756 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17757 
17758 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17759 
17760 return {h, x.e + y.e + 64};
17761 }
17762 
17763 /*!
17764 @brief normalize x such that the significand is >= 2^(q-1)
17765 @pre x.f != 0
17766 */
17767 static diyfp normalize(diyfp x) noexcept
17768 {
17769 JSON_ASSERT(x.f != 0);
17770 
17771 while ((x.f >> 63u) == 0)
17772 {
17773 x.f <<= 1u;
17774 x.e--;
17775 }
17776 
17777 return x;
17778 }
17779 
17780 /*!
17781 @brief normalize x such that the result has the exponent E
17782 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
17783 */
17784 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17785 {
17786 const int delta = x.e - target_exponent;
17787 
17788 JSON_ASSERT(delta >= 0);
17789 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17790 
17791 return {x.f << delta, target_exponent};
17792 }
17793};
17794 
17795struct boundaries
17796{
17797 diyfp w;
17798 diyfp minus;
17799 diyfp plus;
17800};
17801 
17802/*!
17803Compute the (normalized) diyfp representing the input number 'value' and its
17804boundaries.
17805 
17806@pre value must be finite and positive
17807*/
17808template<typename FloatType>
17809boundaries compute_boundaries(FloatType value)
17810{
17811 JSON_ASSERT(std::isfinite(value));
17812 JSON_ASSERT(value > 0);
17813 
17814 // Convert the IEEE representation into a diyfp.
17815 //
17816 // If v is denormal:
17817 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17818 // If v is normalized:
17819 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17820 
17821 static_assert(std::numeric_limits<FloatType>::is_iec559,
17822 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17823 
17824 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17825 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17826 constexpr int kMinExp = 1 - kBias;
17827 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17828 
17829 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17830 
17831 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17832 const std::uint64_t E = bits >> (kPrecision - 1);
17833 const std::uint64_t F = bits & (kHiddenBit - 1);
17834 
17835 const bool is_denormal = E == 0;
17836 const diyfp v = is_denormal
17837 ? diyfp(F, kMinExp)
17838 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17839 
17840 // Compute the boundaries m- and m+ of the floating-point value
17841 // v = f * 2^e.
17842 //
17843 // Determine v- and v+, the floating-point predecessor and successor if v,
17844 // respectively.
17845 //
17846 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17847 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17848 //
17849 // v+ = v + 2^e
17850 //
17851 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17852 // between m- and m+ round to v, regardless of how the input rounding
17853 // algorithm breaks ties.
17854 //
17855 // ---+-------------+-------------+-------------+-------------+--- (A)
17856 // v- m- v m+ v+
17857 //
17858 // -----------------+------+------+-------------+-------------+--- (B)
17859 // v- m- v m+ v+
17860 
17861 const bool lower_boundary_is_closer = F == 0 && E > 1;
17862 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17863 const diyfp m_minus = lower_boundary_is_closer
17864 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17865 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17866 
17867 // Determine the normalized w+ = m+.
17868 const diyfp w_plus = diyfp::normalize(m_plus);
17869 
17870 // Determine w- = m- such that e_(w-) = e_(w+).
17871 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17872 
17873 return {diyfp::normalize(v), w_minus, w_plus};
17874}
17875 
17876// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17877// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17878// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17879//
17880// alpha <= e = e_c + e_w + q <= gamma
17881//
17882// or
17883//
17884// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17885// <= f_c * f_w * 2^gamma
17886//
17887// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17888//
17889// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17890//
17891// or
17892//
17893// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17894//
17895// The choice of (alpha,gamma) determines the size of the table and the form of
17896// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17897// in practice:
17898//
17899// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17900// processed independently: An integral part p1, and a fractional part p2:
17901//
17902// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17903// = (f div 2^-e) + (f mod 2^-e) * 2^e
17904// = p1 + p2 * 2^e
17905//
17906// The conversion of p1 into decimal form requires a series of divisions and
17907// modulos by (a power of) 10. These operations are faster for 32-bit than for
17908// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17909// achieved by choosing
17910//
17911// -e >= 32 or e <= -32 := gamma
17912//
17913// In order to convert the fractional part
17914//
17915// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17916//
17917// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17918// d[-i] are extracted in order:
17919//
17920// (10 * p2) div 2^-e = d[-1]
17921// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17922//
17923// The multiplication by 10 must not overflow. It is sufficient to choose
17924//
17925// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17926//
17927// Since p2 = f mod 2^-e < 2^-e,
17928//
17929// -e <= 60 or e >= -60 := alpha
17930 
17931constexpr int kAlpha = -60;
17932constexpr int kGamma = -32;
17933 
17934struct cached_power // c = f * 2^e ~= 10^k
17935{
17936 std::uint64_t f;
17937 int e;
17938 int k;
17939};
17940 
17941/*!
17942For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
17943power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
17944satisfies (Definition 3.2 from [1])
17945 
17946 alpha <= e_c + e + q <= gamma.
17947*/
17948inline cached_power get_cached_power_for_binary_exponent(int e)
17949{
17950 // Now
17951 //
17952 // alpha <= e_c + e + q <= gamma (1)
17953 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17954 //
17955 // and since the c's are normalized, 2^(q-1) <= f_c,
17956 //
17957 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17958 // ==> 2^(alpha - e - 1) <= c
17959 //
17960 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17961 //
17962 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17963 // = ceil( (alpha - e - 1) * log_10(2) )
17964 //
17965 // From the paper:
17966 // "In theory the result of the procedure could be wrong since c is rounded,
17967 // and the computation itself is approximated [...]. In practice, however,
17968 // this simple function is sufficient."
17969 //
17970 // For IEEE double precision floating-point numbers converted into
17971 // normalized diyfp's w = f * 2^e, with q = 64,
17972 //
17973 // e >= -1022 (min IEEE exponent)
17974 // -52 (p - 1)
17975 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17976 // -11 (normalize the diyfp)
17977 // = -1137
17978 //
17979 // and
17980 //
17981 // e <= +1023 (max IEEE exponent)
17982 // -52 (p - 1)
17983 // -11 (normalize the diyfp)
17984 // = 960
17985 //
17986 // This binary exponent range [-1137,960] results in a decimal exponent
17987 // range [-307,324]. One does not need to store a cached power for each
17988 // k in this range. For each such k it suffices to find a cached power
17989 // such that the exponent of the product lies in [alpha,gamma].
17990 // This implies that the difference of the decimal exponents of adjacent
17991 // table entries must be less than or equal to
17992 //
17993 // floor( (gamma - alpha) * log_10(2) ) = 8.
17994 //
17995 // (A smaller distance gamma-alpha would require a larger table.)
17996 
17997 // NB:
17998 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17999 
18000 constexpr int kCachedPowersMinDecExp = -300;
18001 constexpr int kCachedPowersDecStep = 8;
18002 
18003 static constexpr std::array<cached_power, 79> kCachedPowers =
18004 {
18005 {
18006 { 0xAB70FE17C79AC6CA, -1060, -300 },
18007 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18008 { 0xBE5691EF416BD60C, -1007, -284 },
18009 { 0x8DD01FAD907FFC3C, -980, -276 },
18010 { 0xD3515C2831559A83, -954, -268 },
18011 { 0x9D71AC8FADA6C9B5, -927, -260 },
18012 { 0xEA9C227723EE8BCB, -901, -252 },
18013 { 0xAECC49914078536D, -874, -244 },
18014 { 0x823C12795DB6CE57, -847, -236 },
18015 { 0xC21094364DFB5637, -821, -228 },
18016 { 0x9096EA6F3848984F, -794, -220 },
18017 { 0xD77485CB25823AC7, -768, -212 },
18018 { 0xA086CFCD97BF97F4, -741, -204 },
18019 { 0xEF340A98172AACE5, -715, -196 },
18020 { 0xB23867FB2A35B28E, -688, -188 },
18021 { 0x84C8D4DFD2C63F3B, -661, -180 },
18022 { 0xC5DD44271AD3CDBA, -635, -172 },
18023 { 0x936B9FCEBB25C996, -608, -164 },
18024 { 0xDBAC6C247D62A584, -582, -156 },
18025 { 0xA3AB66580D5FDAF6, -555, -148 },
18026 { 0xF3E2F893DEC3F126, -529, -140 },
18027 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18028 { 0x87625F056C7C4A8B, -475, -124 },
18029 { 0xC9BCFF6034C13053, -449, -116 },
18030 { 0x964E858C91BA2655, -422, -108 },
18031 { 0xDFF9772470297EBD, -396, -100 },
18032 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18033 { 0xF8A95FCF88747D94, -343, -84 },
18034 { 0xB94470938FA89BCF, -316, -76 },
18035 { 0x8A08F0F8BF0F156B, -289, -68 },
18036 { 0xCDB02555653131B6, -263, -60 },
18037 { 0x993FE2C6D07B7FAC, -236, -52 },
18038 { 0xE45C10C42A2B3B06, -210, -44 },
18039 { 0xAA242499697392D3, -183, -36 },
18040 { 0xFD87B5F28300CA0E, -157, -28 },
18041 { 0xBCE5086492111AEB, -130, -20 },
18042 { 0x8CBCCC096F5088CC, -103, -12 },
18043 { 0xD1B71758E219652C, -77, -4 },
18044 { 0x9C40000000000000, -50, 4 },
18045 { 0xE8D4A51000000000, -24, 12 },
18046 { 0xAD78EBC5AC620000, 3, 20 },
18047 { 0x813F3978F8940984, 30, 28 },
18048 { 0xC097CE7BC90715B3, 56, 36 },
18049 { 0x8F7E32CE7BEA5C70, 83, 44 },
18050 { 0xD5D238A4ABE98068, 109, 52 },
18051 { 0x9F4F2726179A2245, 136, 60 },
18052 { 0xED63A231D4C4FB27, 162, 68 },
18053 { 0xB0DE65388CC8ADA8, 189, 76 },
18054 { 0x83C7088E1AAB65DB, 216, 84 },
18055 { 0xC45D1DF942711D9A, 242, 92 },
18056 { 0x924D692CA61BE758, 269, 100 },
18057 { 0xDA01EE641A708DEA, 295, 108 },
18058 { 0xA26DA3999AEF774A, 322, 116 },
18059 { 0xF209787BB47D6B85, 348, 124 },
18060 { 0xB454E4A179DD1877, 375, 132 },
18061 { 0x865B86925B9BC5C2, 402, 140 },
18062 { 0xC83553C5C8965D3D, 428, 148 },
18063 { 0x952AB45CFA97A0B3, 455, 156 },
18064 { 0xDE469FBD99A05FE3, 481, 164 },
18065 { 0xA59BC234DB398C25, 508, 172 },
18066 { 0xF6C69A72A3989F5C, 534, 180 },
18067 { 0xB7DCBF5354E9BECE, 561, 188 },
18068 { 0x88FCF317F22241E2, 588, 196 },
18069 { 0xCC20CE9BD35C78A5, 614, 204 },
18070 { 0x98165AF37B2153DF, 641, 212 },
18071 { 0xE2A0B5DC971F303A, 667, 220 },
18072 { 0xA8D9D1535CE3B396, 694, 228 },
18073 { 0xFB9B7CD9A4A7443C, 720, 236 },
18074 { 0xBB764C4CA7A44410, 747, 244 },
18075 { 0x8BAB8EEFB6409C1A, 774, 252 },
18076 { 0xD01FEF10A657842C, 800, 260 },
18077 { 0x9B10A4E5E9913129, 827, 268 },
18078 { 0xE7109BFBA19C0C9D, 853, 276 },
18079 { 0xAC2820D9623BF429, 880, 284 },
18080 { 0x80444B5E7AA7CF85, 907, 292 },
18081 { 0xBF21E44003ACDD2D, 933, 300 },
18082 { 0x8E679C2F5E44FF8F, 960, 308 },
18083 { 0xD433179D9C8CB841, 986, 316 },
18084 { 0x9E19DB92B4E31BA9, 1013, 324 },
18085 }
18086 };
18087 
18088 // This computation gives exactly the same results for k as
18089 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18090 // for |e| <= 1500, but doesn't require floating-point operations.
18091 // NB: log_10(2) ~= 78913 / 2^18
18092 JSON_ASSERT(e >= -1500);
18093 JSON_ASSERT(e <= 1500);
18094 const int f = kAlpha - e - 1;
18095 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18096 
18097 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18098 JSON_ASSERT(index >= 0);
18099 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18100 
18101 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18102 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18103 JSON_ASSERT(kGamma >= cached.e + e + 64);
18104 
18105 return cached;
18106}
18107 
18108/*!
18109For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
18110For n == 0, returns 1 and sets pow10 := 1.
18111*/
18112inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18113{
18114 // LCOV_EXCL_START
18115 if (n >= 1000000000)
18116 {
18117 pow10 = 1000000000;
18118 return 10;
18119 }
18120 // LCOV_EXCL_STOP
18121 if (n >= 100000000)
18122 {
18123 pow10 = 100000000;
18124 return 9;
18125 }
18126 if (n >= 10000000)
18127 {
18128 pow10 = 10000000;
18129 return 8;
18130 }
18131 if (n >= 1000000)
18132 {
18133 pow10 = 1000000;
18134 return 7;
18135 }
18136 if (n >= 100000)
18137 {
18138 pow10 = 100000;
18139 return 6;
18140 }
18141 if (n >= 10000)
18142 {
18143 pow10 = 10000;
18144 return 5;
18145 }
18146 if (n >= 1000)
18147 {
18148 pow10 = 1000;
18149 return 4;
18150 }
18151 if (n >= 100)
18152 {
18153 pow10 = 100;
18154 return 3;
18155 }
18156 if (n >= 10)
18157 {
18158 pow10 = 10;
18159 return 2;
18160 }
18161 
18162 pow10 = 1;
18163 return 1;
18164}
18165 
18166inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18167 std::uint64_t rest, std::uint64_t ten_k)
18168{
18169 JSON_ASSERT(len >= 1);
18170 JSON_ASSERT(dist <= delta);
18171 JSON_ASSERT(rest <= delta);
18172 JSON_ASSERT(ten_k > 0);
18173 
18174 // <--------------------------- delta ---->
18175 // <---- dist --------->
18176 // --------------[------------------+-------------------]--------------
18177 // M- w M+
18178 //
18179 // ten_k
18180 // <------>
18181 // <---- rest ---->
18182 // --------------[------------------+----+--------------]--------------
18183 // w V
18184 // = buf * 10^k
18185 //
18186 // ten_k represents a unit-in-the-last-place in the decimal representation
18187 // stored in buf.
18188 // Decrement buf by ten_k while this takes buf closer to w.
18189 
18190 // The tests are written in this order to avoid overflow in unsigned
18191 // integer arithmetic.
18192 
18193 while (rest < dist
18194 && delta - rest >= ten_k
18195 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18196 {
18197 JSON_ASSERT(buf[len - 1] != '0');
18198 buf[len - 1]--;
18199 rest += ten_k;
18200 }
18201}
18202 
18203/*!
18204Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
18205M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
18206*/
18207inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18208 diyfp M_minus, diyfp w, diyfp M_plus)
18209{
18210 static_assert(kAlpha >= -60, "internal error");
18211 static_assert(kGamma <= -32, "internal error");
18212 
18213 // Generates the digits (and the exponent) of a decimal floating-point
18214 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18215 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18216 //
18217 // <--------------------------- delta ---->
18218 // <---- dist --------->
18219 // --------------[------------------+-------------------]--------------
18220 // M- w M+
18221 //
18222 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18223 // V is in [M-,M+].
18224 
18225 JSON_ASSERT(M_plus.e >= kAlpha);
18226 JSON_ASSERT(M_plus.e <= kGamma);
18227 
18228 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18229 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18230 
18231 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18232 //
18233 // M+ = f * 2^e
18234 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18235 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18236 // = p1 + p2 * 2^e
18237 
18238 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18239 
18240 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.)
18241 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18242 
18243 // 1)
18244 //
18245 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18246 
18247 JSON_ASSERT(p1 > 0);
18248 
18249 std::uint32_t pow10{};
18250 const int k = find_largest_pow10(p1, pow10);
18251 
18252 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18253 //
18254 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18255 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18256 //
18257 // M+ = p1 + p2 * 2^e
18258 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18259 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18260 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18261 //
18262 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18263 //
18264 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18265 //
18266 // but stop as soon as
18267 //
18268 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18269 
18270 int n = k;
18271 while (n > 0)
18272 {
18273 // Invariants:
18274 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18275 // pow10 = 10^(n-1) <= p1 < 10^n
18276 //
18277 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18278 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18279 //
18280 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18281 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18282 //
18283 JSON_ASSERT(d <= 9);
18284 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18285 //
18286 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18287 //
18288 p1 = r;
18289 n--;
18290 //
18291 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18292 // pow10 = 10^n
18293 //
18294 
18295 // Now check if enough digits have been generated.
18296 // Compute
18297 //
18298 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18299 //
18300 // Note:
18301 // Since rest and delta share the same exponent e, it suffices to
18302 // compare the significands.
18303 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18304 if (rest <= delta)
18305 {
18306 // V = buffer * 10^n, with M- <= V <= M+.
18307 
18308 decimal_exponent += n;
18309 
18310 // We may now just stop. But instead look if the buffer could be
18311 // decremented to bring V closer to w.
18312 //
18313 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18314 // The rounding procedure works with diyfp's with an implicit
18315 // exponent of e.
18316 //
18317 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18318 //
18319 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18320 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18321 
18322 return;
18323 }
18324 
18325 pow10 /= 10;
18326 //
18327 // pow10 = 10^(n-1) <= p1 < 10^n
18328 // Invariants restored.
18329 }
18330 
18331 // 2)
18332 //
18333 // The digits of the integral part have been generated:
18334 //
18335 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18336 // = buffer + p2 * 2^e
18337 //
18338 // Now generate the digits of the fractional part p2 * 2^e.
18339 //
18340 // Note:
18341 // No decimal point is generated: the exponent is adjusted instead.
18342 //
18343 // p2 actually represents the fraction
18344 //
18345 // p2 * 2^e
18346 // = p2 / 2^-e
18347 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18348 //
18349 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18350 //
18351 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18352 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18353 //
18354 // using
18355 //
18356 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18357 // = ( d) * 2^-e + ( r)
18358 //
18359 // or
18360 // 10^m * p2 * 2^e = d + r * 2^e
18361 //
18362 // i.e.
18363 //
18364 // M+ = buffer + p2 * 2^e
18365 // = buffer + 10^-m * (d + r * 2^e)
18366 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18367 //
18368 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18369 
18370 JSON_ASSERT(p2 > delta);
18371 
18372 int m = 0;
18373 for (;;)
18374 {
18375 // Invariant:
18376 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18377 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18378 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18379 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18380 //
18381 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18382 p2 *= 10;
18383 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18384 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18385 //
18386 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18387 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18388 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18389 //
18390 JSON_ASSERT(d <= 9);
18391 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18392 //
18393 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18394 //
18395 p2 = r;
18396 m++;
18397 //
18398 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18399 // Invariant restored.
18400 
18401 // Check if enough digits have been generated.
18402 //
18403 // 10^-m * p2 * 2^e <= delta * 2^e
18404 // p2 * 2^e <= 10^m * delta * 2^e
18405 // p2 <= 10^m * delta
18406 delta *= 10;
18407 dist *= 10;
18408 if (p2 <= delta)
18409 {
18410 break;
18411 }
18412 }
18413 
18414 // V = buffer * 10^-m, with M- <= V <= M+.
18415 
18416 decimal_exponent -= m;
18417 
18418 // 1 ulp in the decimal representation is now 10^-m.
18419 // Since delta and dist are now scaled by 10^m, we need to do the
18420 // same with ulp in order to keep the units in sync.
18421 //
18422 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18423 //
18424 const std::uint64_t ten_m = one.f;
18425 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18426 
18427 // By construction this algorithm generates the shortest possible decimal
18428 // number (Loitsch, Theorem 6.2) which rounds back to w.
18429 // For an input number of precision p, at least
18430 //
18431 // N = 1 + ceil(p * log_10(2))
18432 //
18433 // decimal digits are sufficient to identify all binary floating-point
18434 // numbers (Matula, "In-and-Out conversions").
18435 // This implies that the algorithm does not produce more than N decimal
18436 // digits.
18437 //
18438 // N = 17 for p = 53 (IEEE double precision)
18439 // N = 9 for p = 24 (IEEE single precision)
18440}
18441 
18442/*!
18443v = buf * 10^decimal_exponent
18444len is the length of the buffer (number of decimal digits)
18445The buffer must be large enough, i.e. >= max_digits10.
18446*/
18447JSON_HEDLEY_NON_NULL(1)
18448inline void grisu2(char* buf, int& len, int& decimal_exponent,
18449 diyfp m_minus, diyfp v, diyfp m_plus)
18450{
18451 JSON_ASSERT(m_plus.e == m_minus.e);
18452 JSON_ASSERT(m_plus.e == v.e);
18453 
18454 // --------(-----------------------+-----------------------)-------- (A)
18455 // m- v m+
18456 //
18457 // --------------------(-----------+-----------------------)-------- (B)
18458 // m- v m+
18459 //
18460 // First scale v (and m- and m+) such that the exponent is in the range
18461 // [alpha, gamma].
18462 
18463 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18464 
18465 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18466 
18467 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18468 const diyfp w = diyfp::mul(v, c_minus_k);
18469 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18470 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18471 
18472 // ----(---+---)---------------(---+---)---------------(---+---)----
18473 // w- w w+
18474 // = c*m- = c*v = c*m+
18475 //
18476 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18477 // w+ are now off by a small amount.
18478 // In fact:
18479 //
18480 // w - v * 10^k < 1 ulp
18481 //
18482 // To account for this inaccuracy, add resp. subtract 1 ulp.
18483 //
18484 // --------+---[---------------(---+---)---------------]---+--------
18485 // w- M- w M+ w+
18486 //
18487 // Now any number in [M-, M+] (bounds included) will round to w when input,
18488 // regardless of how the input rounding algorithm breaks ties.
18489 //
18490 // And digit_gen generates the shortest possible such number in [M-, M+].
18491 // Note that this does not mean that Grisu2 always generates the shortest
18492 // possible number in the interval (m-, m+).
18493 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18494 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18495 
18496 decimal_exponent = -cached.k; // = -(-k) = k
18497 
18498 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18499}
18500 
18501/*!
18502v = buf * 10^decimal_exponent
18503len is the length of the buffer (number of decimal digits)
18504The buffer must be large enough, i.e. >= max_digits10.
18505*/
18506template<typename FloatType>
18507JSON_HEDLEY_NON_NULL(1)
18508void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18509{
18510 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18511 "internal error: not enough precision");
18512 
18513 JSON_ASSERT(std::isfinite(value));
18514 JSON_ASSERT(value > 0);
18515 
18516 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18517 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18518 // decimal representations are not exactly "short".
18519 //
18520 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18521 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18522 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18523 // does.
18524 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18525 // representation using the corresponding std::from_chars function recovers value exactly". That
18526 // indicates that single precision floating-point numbers should be recovered using
18527 // 'std::strtof'.
18528 //
18529 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18530 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18531 // value is off by 1 ulp.
18532#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18533 const boundaries w = compute_boundaries(static_cast<double>(value));
18534#else
18535 const boundaries w = compute_boundaries(value);
18536#endif
18537 
18538 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18539}
18540 
18541/*!
18542@brief appends a decimal representation of e to buf
18543@return a pointer to the element following the exponent.
18544@pre -1000 < e < 1000
18545*/
18546JSON_HEDLEY_NON_NULL(1)
18547JSON_HEDLEY_RETURNS_NON_NULL
18548inline char* append_exponent(char* buf, int e)
18549{
18550 JSON_ASSERT(e > -1000);
18551 JSON_ASSERT(e < 1000);
18552 
18553 if (e < 0)
18554 {
18555 e = -e;
18556 *buf++ = '-';
18557 }
18558 else
18559 {
18560 *buf++ = '+';
18561 }
18562 
18563 auto k = static_cast<std::uint32_t>(e);
18564 if (k < 10)
18565 {
18566 // Always print at least two digits in the exponent.
18567 // This is for compatibility with printf("%g").
18568 *buf++ = '0';
18569 *buf++ = static_cast<char>('0' + k);
18570 }
18571 else if (k < 100)
18572 {
18573 *buf++ = static_cast<char>('0' + (k / 10));
18574 k %= 10;
18575 *buf++ = static_cast<char>('0' + k);
18576 }
18577 else
18578 {
18579 *buf++ = static_cast<char>('0' + (k / 100));
18580 k %= 100;
18581 *buf++ = static_cast<char>('0' + (k / 10));
18582 k %= 10;
18583 *buf++ = static_cast<char>('0' + k);
18584 }
18585 
18586 return buf;
18587}
18588 
18589/*!
18590@brief prettify v = buf * 10^decimal_exponent
18591 
18592If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
18593notation. Otherwise it will be printed in exponential notation.
18594 
18595@pre min_exp < 0
18596@pre max_exp > 0
18597*/
18598JSON_HEDLEY_NON_NULL(1)
18599JSON_HEDLEY_RETURNS_NON_NULL
18600inline char* format_buffer(char* buf, int len, int decimal_exponent,
18601 int min_exp, int max_exp)
18602{
18603 JSON_ASSERT(min_exp < 0);
18604 JSON_ASSERT(max_exp > 0);
18605 
18606 const int k = len;
18607 const int n = len + decimal_exponent;
18608 
18609 // v = buf * 10^(n-k)
18610 // k is the length of the buffer (number of decimal digits)
18611 // n is the position of the decimal point relative to the start of the buffer.
18612 
18613 if (k <= n && n <= max_exp)
18614 {
18615 // digits[000]
18616 // len <= max_exp + 2
18617 
18618 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18619 // Make it look like a floating-point number (#362, #378)
18620 buf[n + 0] = '.';
18621 buf[n + 1] = '0';
18622 return buf + (static_cast<size_t>(n) + 2);
18623 }
18624 
18625 if (0 < n && n <= max_exp)
18626 {
18627 // dig.its
18628 // len <= max_digits10 + 1
18629 
18630 JSON_ASSERT(k > n);
18631 
18632 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18633 buf[n] = '.';
18634 return buf + (static_cast<size_t>(k) + 1U);
18635 }
18636 
18637 if (min_exp < n && n <= 0)
18638 {
18639 // 0.[000]digits
18640 // len <= 2 + (-min_exp - 1) + max_digits10
18641 
18642 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18643 buf[0] = '0';
18644 buf[1] = '.';
18645 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18646 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18647 }
18648 
18649 if (k == 1)
18650 {
18651 // dE+123
18652 // len <= 1 + 5
18653 
18654 buf += 1;
18655 }
18656 else
18657 {
18658 // d.igitsE+123
18659 // len <= max_digits10 + 1 + 5
18660 
18661 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18662 buf[1] = '.';
18663 buf += 1 + static_cast<size_t>(k);
18664 }
18665 
18666 *buf++ = 'e';
18667 return append_exponent(buf, n - 1);
18668}
18669 
18670} // namespace dtoa_impl
18671 
18672/*!
18673@brief generates a decimal representation of the floating-point number value in [first, last).
18674 
18675The format of the resulting decimal representation is similar to printf's %g
18676format. Returns an iterator pointing past-the-end of the decimal representation.
18677 
18678@note The input number must be finite, i.e. NaN's and Inf's are not supported.
18679@note The buffer must be large enough.
18680@note The result is NOT null-terminated.
18681*/
18682template<typename FloatType>
18683JSON_HEDLEY_NON_NULL(1, 2)
18684JSON_HEDLEY_RETURNS_NON_NULL
18685char* to_chars(char* first, const char* last, FloatType value)
18686{
18687 static_cast<void>(last); // maybe unused - fix warning
18688 JSON_ASSERT(std::isfinite(value));
18689 
18690 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18691 if (std::signbit(value))
18692 {
18693 value = -value;
18694 *first++ = '-';
18695 }
18696 
18697#ifdef __GNUC__
18698#pragma GCC diagnostic push
18699#pragma GCC diagnostic ignored "-Wfloat-equal"
18700#endif
18701 if (value == 0) // +-0
18702 {
18703 *first++ = '0';
18704 // Make it look like a floating-point number (#362, #378)
18705 *first++ = '.';
18706 *first++ = '0';
18707 return first;
18708 }
18709#ifdef __GNUC__
18710#pragma GCC diagnostic pop
18711#endif
18712 
18713 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18714 
18715 // Compute v = buffer * 10^decimal_exponent.
18716 // The decimal digits are stored in the buffer, which needs to be interpreted
18717 // as an unsigned decimal integer.
18718 // len is the length of the buffer, i.e. the number of decimal digits.
18719 int len = 0;
18720 int decimal_exponent = 0;
18721 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18722 
18723 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18724 
18725 // Format the buffer like printf("%.*g", prec, value)
18726 constexpr int kMinExp = -4;
18727 // Use digits10 here to increase compatibility with version 2.
18728 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18729 
18730 JSON_ASSERT(last - first >= kMaxExp + 2);
18731 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18732 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18733 
18734 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18735}
18736 
18737} // namespace detail
18738NLOHMANN_JSON_NAMESPACE_END
18739 
18740// #include <nlohmann/detail/exceptions.hpp>
18741 
18742// #include <nlohmann/detail/macro_scope.hpp>
18743 
18744// #include <nlohmann/detail/meta/cpp_future.hpp>
18745 
18746// #include <nlohmann/detail/output/binary_writer.hpp>
18747 
18748// #include <nlohmann/detail/output/output_adapters.hpp>
18749 
18750// #include <nlohmann/detail/string_concat.hpp>
18751 
18752// #include <nlohmann/detail/value_t.hpp>
18753 
18754 
18755NLOHMANN_JSON_NAMESPACE_BEGIN
18756namespace detail
18757{
18758 
18759///////////////////
18760// serialization //
18761///////////////////
18762 
18763/// how to treat decoding errors
18764enum class error_handler_t
18765{
18766 strict, ///< throw a type_error exception in case of invalid UTF-8
18767 replace, ///< replace invalid UTF-8 sequences with U+FFFD
18768 ignore ///< ignore invalid UTF-8 sequences
18769};
18770 
18771template<typename BasicJsonType>
18772class serializer
18773{
18774 using string_t = typename BasicJsonType::string_t;
18775 using number_float_t = typename BasicJsonType::number_float_t;
18776 using number_integer_t = typename BasicJsonType::number_integer_t;
18777 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18778 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18779 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18780 static constexpr std::uint8_t UTF8_REJECT = 1;
18781 
18782 public:
18783 /*!
18784 @param[in] s output stream to serialize to
18785 @param[in] ichar indentation character to use
18786 @param[in] error_handler_ how to react on decoding errors
18787 */
18788 serializer(output_adapter_t<char> s, const char ichar,
18789 error_handler_t error_handler_ = error_handler_t::strict)
18790 : o(std::move(s))
18791 , loc(std::localeconv())
18792 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18793 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18794 , indent_char(ichar)
18795 , indent_string(512, indent_char)
18796 , error_handler(error_handler_)
18797 {}
18798 
18799 // delete because of pointer members
18800 serializer(const serializer&) = delete;
18801 serializer& operator=(const serializer&) = delete;
18802 serializer(serializer&&) = delete;
18803 serializer& operator=(serializer&&) = delete;
18804 ~serializer() = default;
18805 
18806 /*!
18807 @brief internal implementation of the serialization function
18808 
18809 This function is called by the public member function dump and organizes
18810 the serialization internally. The indentation level is propagated as
18811 additional parameter. In case of arrays and objects, the function is
18812 called recursively.
18813 
18814 - strings and object keys are escaped using `escape_string()`
18815 - integer numbers are converted implicitly via `operator<<`
18816 - floating-point numbers are converted to a string using `"%g"` format
18817 - binary values are serialized as objects containing the subtype and the
18818 byte array
18819 
18820 @param[in] val value to serialize
18821 @param[in] pretty_print whether the output shall be pretty-printed
18822 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18823 in the output are escaped with `\uXXXX` sequences, and the result consists
18824 of ASCII characters only.
18825 @param[in] indent_step the indent level
18826 @param[in] current_indent the current indent level (only used internally)
18827 */
18828 void dump(const BasicJsonType& val,
18829 const bool pretty_print,
18830 const bool ensure_ascii,
18831 const unsigned int indent_step,
18832 const unsigned int current_indent = 0)
18833 {
18834 switch (val.m_data.m_type)
18835 {
18836 case value_t::object:
18837 {
18838 if (val.m_data.m_value.object->empty())
18839 {
18840 o->write_characters("{}", 2);
18841 return;
18842 }
18843 
18844 if (pretty_print)
18845 {
18846 o->write_characters("{\n", 2);
18847 
18848 // variable to hold indentation for recursive calls
18849 const auto new_indent = current_indent + indent_step;
18850 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18851 {
18852 indent_string.resize(indent_string.size() * 2, ' ');
18853 }
18854 
18855 // first n-1 elements
18856 auto i = val.m_data.m_value.object->cbegin();
18857 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18858 {
18859 o->write_characters(indent_string.c_str(), new_indent);
18860 o->write_character('\"');
18861 dump_escaped(i->first, ensure_ascii);
18862 o->write_characters("\": ", 3);
18863 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18864 o->write_characters(",\n", 2);
18865 }
18866 
18867 // last element
18868 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18869 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18870 o->write_characters(indent_string.c_str(), new_indent);
18871 o->write_character('\"');
18872 dump_escaped(i->first, ensure_ascii);
18873 o->write_characters("\": ", 3);
18874 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18875 
18876 o->write_character('\n');
18877 o->write_characters(indent_string.c_str(), current_indent);
18878 o->write_character('}');
18879 }
18880 else
18881 {
18882 o->write_character('{');
18883 
18884 // first n-1 elements
18885 auto i = val.m_data.m_value.object->cbegin();
18886 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18887 {
18888 o->write_character('\"');
18889 dump_escaped(i->first, ensure_ascii);
18890 o->write_characters("\":", 2);
18891 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18892 o->write_character(',');
18893 }
18894 
18895 // last element
18896 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18897 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18898 o->write_character('\"');
18899 dump_escaped(i->first, ensure_ascii);
18900 o->write_characters("\":", 2);
18901 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18902 
18903 o->write_character('}');
18904 }
18905 
18906 return;
18907 }
18908 
18909 case value_t::array:
18910 {
18911 if (val.m_data.m_value.array->empty())
18912 {
18913 o->write_characters("[]", 2);
18914 return;
18915 }
18916 
18917 if (pretty_print)
18918 {
18919 o->write_characters("[\n", 2);
18920 
18921 // variable to hold indentation for recursive calls
18922 const auto new_indent = current_indent + indent_step;
18923 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18924 {
18925 indent_string.resize(indent_string.size() * 2, ' ');
18926 }
18927 
18928 // first n-1 elements
18929 for (auto i = val.m_data.m_value.array->cbegin();
18930 i != val.m_data.m_value.array->cend() - 1; ++i)
18931 {
18932 o->write_characters(indent_string.c_str(), new_indent);
18933 dump(*i, true, ensure_ascii, indent_step, new_indent);
18934 o->write_characters(",\n", 2);
18935 }
18936 
18937 // last element
18938 JSON_ASSERT(!val.m_data.m_value.array->empty());
18939 o->write_characters(indent_string.c_str(), new_indent);
18940 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18941 
18942 o->write_character('\n');
18943 o->write_characters(indent_string.c_str(), current_indent);
18944 o->write_character(']');
18945 }
18946 else
18947 {
18948 o->write_character('[');
18949 
18950 // first n-1 elements
18951 for (auto i = val.m_data.m_value.array->cbegin();
18952 i != val.m_data.m_value.array->cend() - 1; ++i)
18953 {
18954 dump(*i, false, ensure_ascii, indent_step, current_indent);
18955 o->write_character(',');
18956 }
18957 
18958 // last element
18959 JSON_ASSERT(!val.m_data.m_value.array->empty());
18960 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18961 
18962 o->write_character(']');
18963 }
18964 
18965 return;
18966 }
18967 
18968 case value_t::string:
18969 {
18970 o->write_character('\"');
18971 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18972 o->write_character('\"');
18973 return;
18974 }
18975 
18976 case value_t::binary:
18977 {
18978 if (pretty_print)
18979 {
18980 o->write_characters("{\n", 2);
18981 
18982 // variable to hold indentation for recursive calls
18983 const auto new_indent = current_indent + indent_step;
18984 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18985 {
18986 indent_string.resize(indent_string.size() * 2, ' ');
18987 }
18988 
18989 o->write_characters(indent_string.c_str(), new_indent);
18990 
18991 o->write_characters("\"bytes\": [", 10);
18992 
18993 if (!val.m_data.m_value.binary->empty())
18994 {
18995 for (auto i = val.m_data.m_value.binary->cbegin();
18996 i != val.m_data.m_value.binary->cend() - 1; ++i)
18997 {
18998 dump_integer(*i);
18999 o->write_characters(", ", 2);
19000 }
19001 dump_integer(val.m_data.m_value.binary->back());
19002 }
19003 
19004 o->write_characters("],\n", 3);
19005 o->write_characters(indent_string.c_str(), new_indent);
19006 
19007 o->write_characters("\"subtype\": ", 11);
19008 if (val.m_data.m_value.binary->has_subtype())
19009 {
19010 dump_integer(val.m_data.m_value.binary->subtype());
19011 }
19012 else
19013 {
19014 o->write_characters("null", 4);
19015 }
19016 o->write_character('\n');
19017 o->write_characters(indent_string.c_str(), current_indent);
19018 o->write_character('}');
19019 }
19020 else
19021 {
19022 o->write_characters("{\"bytes\":[", 10);
19023 
19024 if (!val.m_data.m_value.binary->empty())
19025 {
19026 for (auto i = val.m_data.m_value.binary->cbegin();
19027 i != val.m_data.m_value.binary->cend() - 1; ++i)
19028 {
19029 dump_integer(*i);
19030 o->write_character(',');
19031 }
19032 dump_integer(val.m_data.m_value.binary->back());
19033 }
19034 
19035 o->write_characters("],\"subtype\":", 12);
19036 if (val.m_data.m_value.binary->has_subtype())
19037 {
19038 dump_integer(val.m_data.m_value.binary->subtype());
19039 o->write_character('}');
19040 }
19041 else
19042 {
19043 o->write_characters("null}", 5);
19044 }
19045 }
19046 return;
19047 }
19048 
19049 case value_t::boolean:
19050 {
19051 if (val.m_data.m_value.boolean)
19052 {
19053 o->write_characters("true", 4);
19054 }
19055 else
19056 {
19057 o->write_characters("false", 5);
19058 }
19059 return;
19060 }
19061 
19062 case value_t::number_integer:
19063 {
19064 dump_integer(val.m_data.m_value.number_integer);
19065 return;
19066 }
19067 
19068 case value_t::number_unsigned:
19069 {
19070 dump_integer(val.m_data.m_value.number_unsigned);
19071 return;
19072 }
19073 
19074 case value_t::number_float:
19075 {
19076 dump_float(val.m_data.m_value.number_float);
19077 return;
19078 }
19079 
19080 case value_t::discarded:
19081 {
19082 o->write_characters("<discarded>", 11);
19083 return;
19084 }
19085 
19086 case value_t::null:
19087 {
19088 o->write_characters("null", 4);
19089 return;
19090 }
19091 
19092 default: // LCOV_EXCL_LINE
19093 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19094 }
19095 }
19096 
19097 JSON_PRIVATE_UNLESS_TESTED:
19098 /*!
19099 @brief dump escaped string
19100 
19101 Escape a string by replacing certain special characters by a sequence of an
19102 escape character (backslash) and another character and other control
19103 characters by a sequence of "\u" followed by a four-digit hex
19104 representation. The escaped string is written to output stream @a o.
19105 
19106 @param[in] s the string to escape
19107 @param[in] ensure_ascii whether to escape non-ASCII characters with
19108 \uXXXX sequences
19109 
19110 @complexity Linear in the length of string @a s.
19111 */
19112 void dump_escaped(const string_t& s, const bool ensure_ascii)
19113 {
19114 std::uint32_t codepoint{};
19115 std::uint8_t state = UTF8_ACCEPT;
19116 std::size_t bytes = 0; // number of bytes written to string_buffer
19117 
19118 // number of bytes written at the point of the last valid byte
19119 std::size_t bytes_after_last_accept = 0;
19120 std::size_t undumped_chars = 0;
19121 
19122 for (std::size_t i = 0; i < s.size(); ++i)
19123 {
19124 const auto byte = static_cast<std::uint8_t>(s[i]);
19125 
19126 switch (decode(state, codepoint, byte))
19127 {
19128 case UTF8_ACCEPT: // decode found a new code point
19129 {
19130 switch (codepoint)
19131 {
19132 case 0x08: // backspace
19133 {
19134 string_buffer[bytes++] = '\\';
19135 string_buffer[bytes++] = 'b';
19136 break;
19137 }
19138 
19139 case 0x09: // horizontal tab
19140 {
19141 string_buffer[bytes++] = '\\';
19142 string_buffer[bytes++] = 't';
19143 break;
19144 }
19145 
19146 case 0x0A: // newline
19147 {
19148 string_buffer[bytes++] = '\\';
19149 string_buffer[bytes++] = 'n';
19150 break;
19151 }
19152 
19153 case 0x0C: // formfeed
19154 {
19155 string_buffer[bytes++] = '\\';
19156 string_buffer[bytes++] = 'f';
19157 break;
19158 }
19159 
19160 case 0x0D: // carriage return
19161 {
19162 string_buffer[bytes++] = '\\';
19163 string_buffer[bytes++] = 'r';
19164 break;
19165 }
19166 
19167 case 0x22: // quotation mark
19168 {
19169 string_buffer[bytes++] = '\\';
19170 string_buffer[bytes++] = '\"';
19171 break;
19172 }
19173 
19174 case 0x5C: // reverse solidus
19175 {
19176 string_buffer[bytes++] = '\\';
19177 string_buffer[bytes++] = '\\';
19178 break;
19179 }
19180 
19181 default:
19182 {
19183 // escape control characters (0x00..0x1F) or, if
19184 // ensure_ascii parameter is used, non-ASCII characters
19185 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19186 {
19187 if (codepoint <= 0xFFFF)
19188 {
19189 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19190 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19191 static_cast<std::uint16_t>(codepoint)));
19192 bytes += 6;
19193 }
19194 else
19195 {
19196 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19197 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19198 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19199 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19200 bytes += 12;
19201 }
19202 }
19203 else
19204 {
19205 // copy byte to buffer (all previous bytes
19206 // been copied have in default case above)
19207 string_buffer[bytes++] = s[i];
19208 }
19209 break;
19210 }
19211 }
19212 
19213 // write buffer and reset index; there must be 13 bytes
19214 // left, as this is the maximal number of bytes to be
19215 // written ("\uxxxx\uxxxx\0") for one code point
19216 if (string_buffer.size() - bytes < 13)
19217 {
19218 o->write_characters(string_buffer.data(), bytes);
19219 bytes = 0;
19220 }
19221 
19222 // remember the byte position of this accept
19223 bytes_after_last_accept = bytes;
19224 undumped_chars = 0;
19225 break;
19226 }
19227 
19228 case UTF8_REJECT: // decode found invalid UTF-8 byte
19229 {
19230 switch (error_handler)
19231 {
19232 case error_handler_t::strict:
19233 {
19234 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19235 }
19236 
19237 case error_handler_t::ignore:
19238 case error_handler_t::replace:
19239 {
19240 // in case we saw this character the first time, we
19241 // would like to read it again, because the byte
19242 // may be OK for itself, but just not OK for the
19243 // previous sequence
19244 if (undumped_chars > 0)
19245 {
19246 --i;
19247 }
19248 
19249 // reset length buffer to the last accepted index;
19250 // thus removing/ignoring the invalid characters
19251 bytes = bytes_after_last_accept;
19252 
19253 if (error_handler == error_handler_t::replace)
19254 {
19255 // add a replacement character
19256 if (ensure_ascii)
19257 {
19258 string_buffer[bytes++] = '\\';
19259 string_buffer[bytes++] = 'u';
19260 string_buffer[bytes++] = 'f';
19261 string_buffer[bytes++] = 'f';
19262 string_buffer[bytes++] = 'f';
19263 string_buffer[bytes++] = 'd';
19264 }
19265 else
19266 {
19267 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19268 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19269 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19270 }
19271 
19272 // write buffer and reset index; there must be 13 bytes
19273 // left, as this is the maximal number of bytes to be
19274 // written ("\uxxxx\uxxxx\0") for one code point
19275 if (string_buffer.size() - bytes < 13)
19276 {
19277 o->write_characters(string_buffer.data(), bytes);
19278 bytes = 0;
19279 }
19280 
19281 bytes_after_last_accept = bytes;
19282 }
19283 
19284 undumped_chars = 0;
19285 
19286 // continue processing the string
19287 state = UTF8_ACCEPT;
19288 break;
19289 }
19290 
19291 default: // LCOV_EXCL_LINE
19292 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19293 }
19294 break;
19295 }
19296 
19297 default: // decode found yet incomplete multi-byte code point
19298 {
19299 if (!ensure_ascii)
19300 {
19301 // code point will not be escaped - copy byte to buffer
19302 string_buffer[bytes++] = s[i];
19303 }
19304 ++undumped_chars;
19305 break;
19306 }
19307 }
19308 }
19309 
19310 // we finished processing the string
19311 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19312 {
19313 // write buffer
19314 if (bytes > 0)
19315 {
19316 o->write_characters(string_buffer.data(), bytes);
19317 }
19318 }
19319 else
19320 {
19321 // we finish reading, but do not accept: string was incomplete
19322 switch (error_handler)
19323 {
19324 case error_handler_t::strict:
19325 {
19326 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));
19327 }
19328 
19329 case error_handler_t::ignore:
19330 {
19331 // write all accepted bytes
19332 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19333 break;
19334 }
19335 
19336 case error_handler_t::replace:
19337 {
19338 // write all accepted bytes
19339 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19340 // add a replacement character
19341 if (ensure_ascii)
19342 {
19343 o->write_characters("\\ufffd", 6);
19344 }
19345 else
19346 {
19347 o->write_characters("\xEF\xBF\xBD", 3);
19348 }
19349 break;
19350 }
19351 
19352 default: // LCOV_EXCL_LINE
19353 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19354 }
19355 }
19356 }
19357 
19358 private:
19359 /*!
19360 @brief count digits
19361 
19362 Count the number of decimal (base 10) digits for an input unsigned integer.
19363 
19364 @param[in] x unsigned integer number to count its digits
19365 @return number of decimal digits
19366 */
19367 unsigned int count_digits(number_unsigned_t x) noexcept
19368 {
19369 unsigned int n_digits = 1;
19370 for (;;)
19371 {
19372 if (x < 10)
19373 {
19374 return n_digits;
19375 }
19376 if (x < 100)
19377 {
19378 return n_digits + 1;
19379 }
19380 if (x < 1000)
19381 {
19382 return n_digits + 2;
19383 }
19384 if (x < 10000)
19385 {
19386 return n_digits + 3;
19387 }
19388 x = x / 10000u;
19389 n_digits += 4;
19390 }
19391 }
19392 
19393 /*!
19394 * @brief convert a byte to a uppercase hex representation
19395 * @param[in] byte byte to represent
19396 * @return representation ("00".."FF")
19397 */
19398 static std::string hex_bytes(std::uint8_t byte)
19399 {
19400 std::string result = "FF";
19401 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19402 result[0] = nibble_to_hex[byte / 16];
19403 result[1] = nibble_to_hex[byte % 16];
19404 return result;
19405 }
19406 
19407 // templates to avoid warnings about useless casts
19408 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19409 bool is_negative_number(NumberType x)
19410 {
19411 return x < 0;
19412 }
19413 
19414 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19415 bool is_negative_number(NumberType /*unused*/)
19416 {
19417 return false;
19418 }
19419 
19420 /*!
19421 @brief dump an integer
19422 
19423 Dump a given integer to output stream @a o. Works internally with
19424 @a number_buffer.
19425 
19426 @param[in] x integer number (signed or unsigned) to dump
19427 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
19428 */
19429 template < typename NumberType, detail::enable_if_t <
19430 std::is_integral<NumberType>::value ||
19431 std::is_same<NumberType, number_unsigned_t>::value ||
19432 std::is_same<NumberType, number_integer_t>::value ||
19433 std::is_same<NumberType, binary_char_t>::value,
19434 int > = 0 >
19435 void dump_integer(NumberType x)
19436 {
19437 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19438 {
19439 {
19440 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19441 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19442 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19443 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19444 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19445 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19446 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19447 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19448 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19449 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19450 }
19451 };
19452 
19453 // special case for "0"
19454 if (x == 0)
19455 {
19456 o->write_character('0');
19457 return;
19458 }
19459 
19460 // use a pointer to fill the buffer
19461 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19462 
19463 number_unsigned_t abs_value;
19464 
19465 unsigned int n_chars{};
19466 
19467 if (is_negative_number(x))
19468 {
19469 *buffer_ptr = '-';
19470 abs_value = remove_sign(static_cast<number_integer_t>(x));
19471 
19472 // account one more byte for the minus sign
19473 n_chars = 1 + count_digits(abs_value);
19474 }
19475 else
19476 {
19477 abs_value = static_cast<number_unsigned_t>(x);
19478 n_chars = count_digits(abs_value);
19479 }
19480 
19481 // spare 1 byte for '\0'
19482 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19483 
19484 // jump to the end to generate the string from backward,
19485 // so we later avoid reversing the result
19486 buffer_ptr += n_chars;
19487 
19488 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19489 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19490 while (abs_value >= 100)
19491 {
19492 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19493 abs_value /= 100;
19494 *(--buffer_ptr) = digits_to_99[digits_index][1];
19495 *(--buffer_ptr) = digits_to_99[digits_index][0];
19496 }
19497 
19498 if (abs_value >= 10)
19499 {
19500 const auto digits_index = static_cast<unsigned>(abs_value);
19501 *(--buffer_ptr) = digits_to_99[digits_index][1];
19502 *(--buffer_ptr) = digits_to_99[digits_index][0];
19503 }
19504 else
19505 {
19506 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19507 }
19508 
19509 o->write_characters(number_buffer.data(), n_chars);
19510 }
19511 
19512 /*!
19513 @brief dump a floating-point number
19514 
19515 Dump a given floating-point number to output stream @a o. Works internally
19516 with @a number_buffer.
19517 
19518 @param[in] x floating-point number to dump
19519 */
19520 void dump_float(number_float_t x)
19521 {
19522 // NaN / inf
19523 if (!std::isfinite(x))
19524 {
19525 o->write_characters("null", 4);
19526 return;
19527 }
19528 
19529 // If number_float_t is an IEEE-754 single or double precision number,
19530 // use the Grisu2 algorithm to produce short numbers which are
19531 // guaranteed to round-trip, using strtof and strtod, resp.
19532 //
19533 // NB: The test below works if <long double> == <double>.
19534 static constexpr bool is_ieee_single_or_double
19535 = (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) ||
19536 (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);
19537 
19538 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19539 }
19540 
19541 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19542 {
19543 auto* begin = number_buffer.data();
19544 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19545 
19546 o->write_characters(begin, static_cast<size_t>(end - begin));
19547 }
19548 
19549 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19550 {
19551 // get number of digits for a float -> text -> float round-trip
19552 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19553 
19554 // the actual conversion
19555 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19556 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19557 
19558 // negative value indicates an error
19559 JSON_ASSERT(len > 0);
19560 // check if buffer was large enough
19561 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19562 
19563 // erase thousands separator
19564 if (thousands_sep != '\0')
19565 {
19566 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19567 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19568 std::fill(end, number_buffer.end(), '\0');
19569 JSON_ASSERT((end - number_buffer.begin()) <= len);
19570 len = (end - number_buffer.begin());
19571 }
19572 
19573 // convert decimal point to '.'
19574 if (decimal_point != '\0' && decimal_point != '.')
19575 {
19576 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19577 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19578 if (dec_pos != number_buffer.end())
19579 {
19580 *dec_pos = '.';
19581 }
19582 }
19583 
19584 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19585 
19586 // determine if we need to append ".0"
19587 const bool value_is_int_like =
19588 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19589 [](char c)
19590 {
19591 return c == '.' || c == 'e';
19592 });
19593 
19594 if (value_is_int_like)
19595 {
19596 o->write_characters(".0", 2);
19597 }
19598 }
19599 
19600 /*!
19601 @brief check whether a string is UTF-8 encoded
19602 
19603 The function checks each byte of a string whether it is UTF-8 encoded. The
19604 result of the check is stored in the @a state parameter. The function must
19605 be called initially with state 0 (accept). State 1 means the string must
19606 be rejected, because the current byte is not allowed. If the string is
19607 completely processed, but the state is non-zero, the string ended
19608 prematurely; that is, the last byte indicated more bytes should have
19609 followed.
19610 
19611 @param[in,out] state the state of the decoding
19612 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
19613 @param[in] byte next byte to decode
19614 @return new state
19615 
19616 @note The function has been edited: a std::array is used.
19617 
19618 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
19619 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
19620 */
19621 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19622 {
19623 static const std::array<std::uint8_t, 400> utf8d =
19624 {
19625 {
19626 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
19627 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
19628 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
19629 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
19630 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
19631 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
19632 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
19633 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19634 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19635 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19636 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
19637 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
19638 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
19639 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
19640 }
19641 };
19642 
19643 JSON_ASSERT(byte < utf8d.size());
19644 const std::uint8_t type = utf8d[byte];
19645 
19646 codep = (state != UTF8_ACCEPT)
19647 ? (byte & 0x3fu) | (codep << 6u)
19648 : (0xFFu >> type) & (byte);
19649 
19650 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19651 JSON_ASSERT(index < utf8d.size());
19652 state = utf8d[index];
19653 return state;
19654 }
19655 
19656 /*
19657 * Overload to make the compiler happy while it is instantiating
19658 * dump_integer for number_unsigned_t.
19659 * Must never be called.
19660 */
19661 number_unsigned_t remove_sign(number_unsigned_t x)
19662 {
19663 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19664 return x; // LCOV_EXCL_LINE
19665 }
19666 
19667 /*
19668 * Helper function for dump_integer
19669 *
19670 * This function takes a negative signed integer and returns its absolute
19671 * value as unsigned integer. The plus/minus shuffling is necessary as we can
19672 * not directly remove the sign of an arbitrary signed integer as the
19673 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19674 * #1708 for details.
19675 */
19676 number_unsigned_t remove_sign(number_integer_t x) noexcept
19677 {
19678 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19679 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19680 }
19681 
19682 private:
19683 /// the output of the serializer
19684 output_adapter_t<char> o = nullptr;
19685 
19686 /// a (hopefully) large enough character buffer
19687 std::array<char, 64> number_buffer{{}};
19688 
19689 /// the locale
19690 const std::lconv* loc = nullptr;
19691 /// the locale's thousand separator character
19692 const char thousands_sep = '\0';
19693 /// the locale's decimal point character
19694 const char decimal_point = '\0';
19695 
19696 /// string buffer
19697 std::array<char, 512> string_buffer{{}};
19698 
19699 /// the indentation character
19700 const char indent_char;
19701 /// the indentation string
19702 string_t indent_string;
19703 
19704 /// error_handler how to react on decoding errors
19705 const error_handler_t error_handler;
19706};
19707 
19708} // namespace detail
19709NLOHMANN_JSON_NAMESPACE_END
19710 
19711// #include <nlohmann/detail/value_t.hpp>
19712 
19713// #include <nlohmann/json_fwd.hpp>
19714 
19715// #include <nlohmann/ordered_map.hpp>
19716// __ _____ _____ _____
19717// __| | __| | | | JSON for Modern C++
19718// | | |__ | | | | | | version 3.12.0
19719// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19720//
19721// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19722// SPDX-License-Identifier: MIT
19723 
19724 
19725 
19726#include <functional> // equal_to, less
19727#include <initializer_list> // initializer_list
19728#include <iterator> // input_iterator_tag, iterator_traits
19729#include <memory> // allocator
19730#include <stdexcept> // for out_of_range
19731#include <type_traits> // enable_if, is_convertible
19732#include <utility> // pair
19733#include <vector> // vector
19734 
19735// #include <nlohmann/detail/macro_scope.hpp>
19736 
19737// #include <nlohmann/detail/meta/type_traits.hpp>
19738 
19739 
19740NLOHMANN_JSON_NAMESPACE_BEGIN
19741 
19742/// ordered_map: a minimal map-like container that preserves insertion order
19743/// for use within nlohmann::basic_json<ordered_map>
19744template <class Key, class T, class IgnoredLess = std::less<Key>,
19745 class Allocator = std::allocator<std::pair<const Key, T>>>
19746 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19747{
19748 using key_type = Key;
19749 using mapped_type = T;
19750 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19751 using iterator = typename Container::iterator;
19752 using const_iterator = typename Container::const_iterator;
19753 using size_type = typename Container::size_type;
19754 using value_type = typename Container::value_type;
19755#ifdef JSON_HAS_CPP_14
19756 using key_compare = std::equal_to<>;
19757#else
19758 using key_compare = std::equal_to<Key>;
19759#endif
19760 
19761 // Explicit constructors instead of `using Container::Container`
19762 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19763 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19764 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19765 template <class It>
19766 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19767 : Container{first, last, alloc} {}
19768 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19769 : Container{init, alloc} {}
19770 
19771 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19772 {
19773 for (auto it = this->begin(); it != this->end(); ++it)
19774 {
19775 if (m_compare(it->first, key))
19776 {
19777 return {it, false};
19778 }
19779 }
19780 Container::emplace_back(key, std::forward<T>(t));
19781 return {std::prev(this->end()), true};
19782 }
19783 
19784 template<class KeyType, detail::enable_if_t<
19785 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19786 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19787 {
19788 for (auto it = this->begin(); it != this->end(); ++it)
19789 {
19790 if (m_compare(it->first, key))
19791 {
19792 return {it, false};
19793 }
19794 }
19795 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19796 return {std::prev(this->end()), true};
19797 }
19798 
19799 T& operator[](const key_type& key)
19800 {
19801 return emplace(key, T{}).first->second;
19802 }
19803 
19804 template<class KeyType, detail::enable_if_t<
19805 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19806 T & operator[](KeyType && key)
19807 {
19808 return emplace(std::forward<KeyType>(key), T{}).first->second;
19809 }
19810 
19811 const T& operator[](const key_type& key) const
19812 {
19813 return at(key);
19814 }
19815 
19816 template<class KeyType, detail::enable_if_t<
19817 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19818 const T & operator[](KeyType && key) const
19819 {
19820 return at(std::forward<KeyType>(key));
19821 }
19822 
19823 T& at(const key_type& key)
19824 {
19825 for (auto it = this->begin(); it != this->end(); ++it)
19826 {
19827 if (m_compare(it->first, key))
19828 {
19829 return it->second;
19830 }
19831 }
19832 
19833 JSON_THROW(std::out_of_range("key not found"));
19834 }
19835 
19836 template<class KeyType, detail::enable_if_t<
19837 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19838 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19839 {
19840 for (auto it = this->begin(); it != this->end(); ++it)
19841 {
19842 if (m_compare(it->first, key))
19843 {
19844 return it->second;
19845 }
19846 }
19847 
19848 JSON_THROW(std::out_of_range("key not found"));
19849 }
19850 
19851 const T& at(const key_type& key) const
19852 {
19853 for (auto it = this->begin(); it != this->end(); ++it)
19854 {
19855 if (m_compare(it->first, key))
19856 {
19857 return it->second;
19858 }
19859 }
19860 
19861 JSON_THROW(std::out_of_range("key not found"));
19862 }
19863 
19864 template<class KeyType, detail::enable_if_t<
19865 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19866 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19867 {
19868 for (auto it = this->begin(); it != this->end(); ++it)
19869 {
19870 if (m_compare(it->first, key))
19871 {
19872 return it->second;
19873 }
19874 }
19875 
19876 JSON_THROW(std::out_of_range("key not found"));
19877 }
19878 
19879 size_type erase(const key_type& key)
19880 {
19881 for (auto it = this->begin(); it != this->end(); ++it)
19882 {
19883 if (m_compare(it->first, key))
19884 {
19885 // Since we cannot move const Keys, re-construct them in place
19886 for (auto next = it; ++next != this->end(); ++it)
19887 {
19888 it->~value_type(); // Destroy but keep allocation
19889 new (&*it) value_type{std::move(*next)};
19890 }
19891 Container::pop_back();
19892 return 1;
19893 }
19894 }
19895 return 0;
19896 }
19897 
19898 template<class KeyType, detail::enable_if_t<
19899 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19900 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19901 {
19902 for (auto it = this->begin(); it != this->end(); ++it)
19903 {
19904 if (m_compare(it->first, key))
19905 {
19906 // Since we cannot move const Keys, re-construct them in place
19907 for (auto next = it; ++next != this->end(); ++it)
19908 {
19909 it->~value_type(); // Destroy but keep allocation
19910 new (&*it) value_type{std::move(*next)};
19911 }
19912 Container::pop_back();
19913 return 1;
19914 }
19915 }
19916 return 0;
19917 }
19918 
19919 iterator erase(iterator pos)
19920 {
19921 return erase(pos, std::next(pos));
19922 }
19923 
19924 iterator erase(iterator first, iterator last)
19925 {
19926 if (first == last)
19927 {
19928 return first;
19929 }
19930 
19931 const auto elements_affected = std::distance(first, last);
19932 const auto offset = std::distance(Container::begin(), first);
19933 
19934 // This is the start situation. We need to delete elements_affected
19935 // elements (3 in this example: e, f, g), and need to return an
19936 // iterator past the last deleted element (h in this example).
19937 // Note that offset is the distance from the start of the vector
19938 // to first. We will need this later.
19939 
19940 // [ a, b, c, d, e, f, g, h, i, j ]
19941 // ^ ^
19942 // first last
19943 
19944 // Since we cannot move const Keys, we re-construct them in place.
19945 // We start at first and re-construct (viz. copy) the elements from
19946 // the back of the vector. Example for first iteration:
19947 
19948 // ,--------.
19949 // v | destroy e and re-construct with h
19950 // [ a, b, c, d, e, f, g, h, i, j ]
19951 // ^ ^
19952 // it it + elements_affected
19953 
19954 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19955 {
19956 it->~value_type(); // destroy but keep allocation
19957 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19958 }
19959 
19960 // [ a, b, c, d, h, i, j, h, i, j ]
19961 // ^ ^
19962 // first last
19963 
19964 // remove the unneeded elements at the end of the vector
19965 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19966 
19967 // [ a, b, c, d, h, i, j ]
19968 // ^ ^
19969 // first last
19970 
19971 // first is now pointing past the last deleted element, but we cannot
19972 // use this iterator, because it may have been invalidated by the
19973 // resize call. Instead, we can return begin() + offset.
19974 return Container::begin() + offset;
19975 }
19976 
19977 size_type count(const key_type& key) const
19978 {
19979 for (auto it = this->begin(); it != this->end(); ++it)
19980 {
19981 if (m_compare(it->first, key))
19982 {
19983 return 1;
19984 }
19985 }
19986 return 0;
19987 }
19988 
19989 template<class KeyType, detail::enable_if_t<
19990 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19991 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19992 {
19993 for (auto it = this->begin(); it != this->end(); ++it)
19994 {
19995 if (m_compare(it->first, key))
19996 {
19997 return 1;
19998 }
19999 }
20000 return 0;
20001 }
20002 
20003 iterator find(const key_type& key)
20004 {
20005 for (auto it = this->begin(); it != this->end(); ++it)
20006 {
20007 if (m_compare(it->first, key))
20008 {
20009 return it;
20010 }
20011 }
20012 return Container::end();
20013 }
20014 
20015 template<class KeyType, detail::enable_if_t<
20016 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20017 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20018 {
20019 for (auto it = this->begin(); it != this->end(); ++it)
20020 {
20021 if (m_compare(it->first, key))
20022 {
20023 return it;
20024 }
20025 }
20026 return Container::end();
20027 }
20028 
20029 const_iterator find(const key_type& key) const
20030 {
20031 for (auto it = this->begin(); it != this->end(); ++it)
20032 {
20033 if (m_compare(it->first, key))
20034 {
20035 return it;
20036 }
20037 }
20038 return Container::end();
20039 }
20040 
20041 std::pair<iterator, bool> insert( value_type&& value )
20042 {
20043 return emplace(value.first, std::move(value.second));
20044 }
20045 
20046 std::pair<iterator, bool> insert( const value_type& value )
20047 {
20048 for (auto it = this->begin(); it != this->end(); ++it)
20049 {
20050 if (m_compare(it->first, value.first))
20051 {
20052 return {it, false};
20053 }
20054 }
20055 Container::push_back(value);
20056 return {--this->end(), true};
20057 }
20058 
20059 template<typename InputIt>
20060 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20061 std::input_iterator_tag>::value>::type;
20062 
20063 template<typename InputIt, typename = require_input_iter<InputIt>>
20064 void insert(InputIt first, InputIt last)
20065 {
20066 for (auto it = first; it != last; ++it)
20067 {
20068 insert(*it);
20069 }
20070 }
20071 
20072private:
20073 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20074};
20075 
20076NLOHMANN_JSON_NAMESPACE_END
20077 
20078 
20079#if defined(JSON_HAS_CPP_17)
20080 #if JSON_HAS_STATIC_RTTI
20081 #include <any>
20082 #endif
20083 #include <string_view>
20084#endif
20085 
20086/*!
20087@brief namespace for Niels Lohmann
20088@see https://github.com/nlohmann
20089@since version 1.0.0
20090*/
20091NLOHMANN_JSON_NAMESPACE_BEGIN
20092 
20093/*!
20094@brief a class to store JSON values
20095 
20096@internal
20097@invariant The member variables @a m_value and @a m_type have the following
20098relationship:
20099- If `m_type == value_t::object`, then `m_value.object != nullptr`.
20100- If `m_type == value_t::array`, then `m_value.array != nullptr`.
20101- If `m_type == value_t::string`, then `m_value.string != nullptr`.
20102The invariants are checked by member function assert_invariant().
20103 
20104@note ObjectType trick from https://stackoverflow.com/a/9860911
20105@endinternal
20106 
20107@since version 1.0.0
20108 
20109@nosubgrouping
20110*/
20111NLOHMANN_BASIC_JSON_TPL_DECLARATION
20112class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20113 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20114{
20115 private:
20116 template<detail::value_t> friend struct detail::external_constructor;
20117 
20118 template<typename>
20119 friend class ::nlohmann::json_pointer;
20120 // can be restored when json_pointer backwards compatibility is removed
20121 // friend ::nlohmann::json_pointer<StringType>;
20122 
20123 template<typename BasicJsonType, typename InputType>
20124 friend class ::nlohmann::detail::parser;
20125 friend ::nlohmann::detail::serializer<basic_json>;
20126 template<typename BasicJsonType>
20127 friend class ::nlohmann::detail::iter_impl;
20128 template<typename BasicJsonType, typename CharType>
20129 friend class ::nlohmann::detail::binary_writer;
20130 template<typename BasicJsonType, typename InputType, typename SAX>
20131 friend class ::nlohmann::detail::binary_reader;
20132 template<typename BasicJsonType, typename InputAdapterType>
20133 friend class ::nlohmann::detail::json_sax_dom_parser;
20134 template<typename BasicJsonType, typename InputAdapterType>
20135 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20136 friend class ::nlohmann::detail::exception;
20137 
20138 /// workaround type for MSVC
20139 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20140 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20141 
20142 JSON_PRIVATE_UNLESS_TESTED:
20143 // convenience aliases for types residing in namespace detail;
20144 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20145 
20146 template<typename InputAdapterType>
20147 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20148 InputAdapterType adapter,
20149 detail::parser_callback_t<basic_json>cb = nullptr,
20150 const bool allow_exceptions = true,
20151 const bool ignore_comments = false
20152 )
20153 {
20154 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20155 std::move(cb), allow_exceptions, ignore_comments);
20156 }
20157 
20158 private:
20159 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20160 template<typename BasicJsonType>
20161 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20162 template<typename BasicJsonType>
20163 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20164 template<typename Iterator>
20165 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20166 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20167 
20168 template<typename CharType>
20169 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20170 
20171 template<typename InputType>
20172 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20173 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20174 
20175 JSON_PRIVATE_UNLESS_TESTED:
20176 using serializer = ::nlohmann::detail::serializer<basic_json>;
20177 
20178 public:
20179 using value_t = detail::value_t;
20180 /// JSON Pointer, see @ref nlohmann::json_pointer
20181 using json_pointer = ::nlohmann::json_pointer<StringType>;
20182 template<typename T, typename SFINAE>
20183 using json_serializer = JSONSerializer<T, SFINAE>;
20184 /// how to treat decoding errors
20185 using error_handler_t = detail::error_handler_t;
20186 /// how to treat CBOR tags
20187 using cbor_tag_handler_t = detail::cbor_tag_handler_t;
20188 /// how to encode BJData
20189 using bjdata_version_t = detail::bjdata_version_t;
20190 /// helper type for initializer lists of basic_json values
20191 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20192 
20193 using input_format_t = detail::input_format_t;
20194 /// SAX interface type, see @ref nlohmann::json_sax
20195 using json_sax_t = json_sax<basic_json>;
20196 
20197 ////////////////
20198 // exceptions //
20199 ////////////////
20200 
20201 /// @name exceptions
20202 /// Classes to implement user-defined exceptions.
20203 /// @{
20204 
20205 using exception = detail::exception;
20206 using parse_error = detail::parse_error;
20207 using invalid_iterator = detail::invalid_iterator;
20208 using type_error = detail::type_error;
20209 using out_of_range = detail::out_of_range;
20210 using other_error = detail::other_error;
20211 
20212 /// @}
20213 
20214 /////////////////////
20215 // container types //
20216 /////////////////////
20217 
20218 /// @name container types
20219 /// The canonic container types to use @ref basic_json like any other STL
20220 /// container.
20221 /// @{
20222 
20223 /// the type of elements in a basic_json container
20224 using value_type = basic_json;
20225 
20226 /// the type of an element reference
20227 using reference = value_type&;
20228 /// the type of an element const reference
20229 using const_reference = const value_type&;
20230 
20231 /// a type to represent differences between iterators
20232 using difference_type = std::ptrdiff_t;
20233 /// a type to represent container sizes
20234 using size_type = std::size_t;
20235 
20236 /// the allocator type
20237 using allocator_type = AllocatorType<basic_json>;
20238 
20239 /// the type of an element pointer
20240 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20241 /// the type of an element const pointer
20242 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20243 
20244 /// an iterator for a basic_json container
20245 using iterator = iter_impl<basic_json>;
20246 /// a const iterator for a basic_json container
20247 using const_iterator = iter_impl<const basic_json>;
20248 /// a reverse iterator for a basic_json container
20249 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20250 /// a const reverse iterator for a basic_json container
20251 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20252 
20253 /// @}
20254 
20255 /// @brief returns the allocator associated with the container
20256 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
20257 static allocator_type get_allocator()
20258 {
20259 return allocator_type();
20260 }
20261 
20262 /// @brief returns version information on the library
20263 /// @sa https://json.nlohmann.me/api/basic_json/meta/
20264 JSON_HEDLEY_WARN_UNUSED_RESULT
20265 static basic_json meta()
20266 {
20267 basic_json result;
20268 
20269 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20270 result["name"] = "JSON for Modern C++";
20271 result["url"] = "https://github.com/nlohmann/json";
20272 result["version"]["string"] =
20273 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20274 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20275 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20276 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20277 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20278 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20279 
20280#ifdef _WIN32
20281 result["platform"] = "win32";
20282#elif defined __linux__
20283 result["platform"] = "linux";
20284#elif defined __APPLE__
20285 result["platform"] = "apple";
20286#elif defined __unix__
20287 result["platform"] = "unix";
20288#else
20289 result["platform"] = "unknown";
20290#endif
20291 
20292#if defined(__ICC) || defined(__INTEL_COMPILER)
20293 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20294#elif defined(__clang__)
20295 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20296#elif defined(__GNUC__) || defined(__GNUG__)
20297 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20298 std::to_string(__GNUC__), '.',
20299 std::to_string(__GNUC_MINOR__), '.',
20300 std::to_string(__GNUC_PATCHLEVEL__))
20301 }
20302 };
20303#elif defined(__HP_cc) || defined(__HP_aCC)
20304 result["compiler"] = "hp"
20305#elif defined(__IBMCPP__)
20306 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20307#elif defined(_MSC_VER)
20308 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20309#elif defined(__PGI)
20310 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20311#elif defined(__SUNPRO_CC)
20312 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20313#else
20314 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20315#endif
20316 
20317#if defined(_MSVC_LANG)
20318 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20319#elif defined(__cplusplus)
20320 result["compiler"]["c++"] = std::to_string(__cplusplus);
20321#else
20322 result["compiler"]["c++"] = "unknown";
20323#endif
20324 return result;
20325 }
20326 
20327 ///////////////////////////
20328 // JSON value data types //
20329 ///////////////////////////
20330 
20331 /// @name JSON value data types
20332 /// The data types to store a JSON value. These types are derived from
20333 /// the template arguments passed to class @ref basic_json.
20334 /// @{
20335 
20336 /// @brief default object key comparator type
20337 /// The actual object key comparator type (@ref object_comparator_t) may be
20338 /// different.
20339 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
20340#if defined(JSON_HAS_CPP_14)
20341 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20342 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20343 using default_object_comparator_t = std::less<>;
20344#else
20345 using default_object_comparator_t = std::less<StringType>;
20346#endif
20347 
20348 /// @brief a type for an object
20349 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
20350 using object_t = ObjectType<StringType,
20351 basic_json,
20352 default_object_comparator_t,
20353 AllocatorType<std::pair<const StringType,
20354 basic_json>>>;
20355 
20356 /// @brief a type for an array
20357 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
20358 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20359 
20360 /// @brief a type for a string
20361 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
20362 using string_t = StringType;
20363 
20364 /// @brief a type for a boolean
20365 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
20366 using boolean_t = BooleanType;
20367 
20368 /// @brief a type for a number (integer)
20369 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
20370 using number_integer_t = NumberIntegerType;
20371 
20372 /// @brief a type for a number (unsigned)
20373 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
20374 using number_unsigned_t = NumberUnsignedType;
20375 
20376 /// @brief a type for a number (floating-point)
20377 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
20378 using number_float_t = NumberFloatType;
20379 
20380 /// @brief a type for a packed binary type
20381 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
20382 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20383 
20384 /// @brief object key comparator type
20385 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
20386 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
20387 
20388 /// @}
20389 
20390 private:
20391 
20392 /// helper for exception-safe object creation
20393 template<typename T, typename... Args>
20394 JSON_HEDLEY_RETURNS_NON_NULL
20395 static T* create(Args&& ... args)
20396 {
20397 AllocatorType<T> alloc;
20398 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20399 
20400 auto deleter = [&](T * obj)
20401 {
20402 AllocatorTraits::deallocate(alloc, obj, 1);
20403 };
20404 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20405 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20406 JSON_ASSERT(obj != nullptr);
20407 return obj.release();
20408 }
20409 
20410 ////////////////////////
20411 // JSON value storage //
20412 ////////////////////////
20413 
20414 JSON_PRIVATE_UNLESS_TESTED:
20415 /*!
20416 @brief a JSON value
20417 
20418 The actual storage for a JSON value of the @ref basic_json class. This
20419 union combines the different storage types for the JSON value types
20420 defined in @ref value_t.
20421 
20422 JSON type | value_t type | used type
20423 --------- | --------------- | ------------------------
20424 object | object | pointer to @ref object_t
20425 array | array | pointer to @ref array_t
20426 string | string | pointer to @ref string_t
20427 boolean | boolean | @ref boolean_t
20428 number | number_integer | @ref number_integer_t
20429 number | number_unsigned | @ref number_unsigned_t
20430 number | number_float | @ref number_float_t
20431 binary | binary | pointer to @ref binary_t
20432 null | null | *no value is stored*
20433 
20434 @note Variable-length types (objects, arrays, and strings) are stored as
20435 pointers. The size of the union should not exceed 64 bits if the default
20436 value types are used.
20437 
20438 @since version 1.0.0
20439 */
20440 union json_value
20441 {
20442 /// object (stored with pointer to save storage)
20443 object_t* object;
20444 /// array (stored with pointer to save storage)
20445 array_t* array;
20446 /// string (stored with pointer to save storage)
20447 string_t* string;
20448 /// binary (stored with pointer to save storage)
20449 binary_t* binary;
20450 /// boolean
20451 boolean_t boolean;
20452 /// number (integer)
20453 number_integer_t number_integer;
20454 /// number (unsigned integer)
20455 number_unsigned_t number_unsigned;
20456 /// number (floating-point)
20457 number_float_t number_float;
20458 
20459 /// default constructor (for null values)
20460 json_value() = default;
20461 /// constructor for booleans
20462 json_value(boolean_t v) noexcept : boolean(v) {}
20463 /// constructor for numbers (integer)
20464 json_value(number_integer_t v) noexcept : number_integer(v) {}
20465 /// constructor for numbers (unsigned)
20466 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20467 /// constructor for numbers (floating-point)
20468 json_value(number_float_t v) noexcept : number_float(v) {}
20469 /// constructor for empty values of a given type
20470 json_value(value_t t)
20471 {
20472 switch (t)
20473 {
20474 case value_t::object:
20475 {
20476 object = create<object_t>();
20477 break;
20478 }
20479 
20480 case value_t::array:
20481 {
20482 array = create<array_t>();
20483 break;
20484 }
20485 
20486 case value_t::string:
20487 {
20488 string = create<string_t>("");
20489 break;
20490 }
20491 
20492 case value_t::binary:
20493 {
20494 binary = create<binary_t>();
20495 break;
20496 }
20497 
20498 case value_t::boolean:
20499 {
20500 boolean = static_cast<boolean_t>(false);
20501 break;
20502 }
20503 
20504 case value_t::number_integer:
20505 {
20506 number_integer = static_cast<number_integer_t>(0);
20507 break;
20508 }
20509 
20510 case value_t::number_unsigned:
20511 {
20512 number_unsigned = static_cast<number_unsigned_t>(0);
20513 break;
20514 }
20515 
20516 case value_t::number_float:
20517 {
20518 number_float = static_cast<number_float_t>(0.0);
20519 break;
20520 }
20521 
20522 case value_t::null:
20523 {
20524 object = nullptr; // silence warning, see #821
20525 break;
20526 }
20527 
20528 case value_t::discarded:
20529 default:
20530 {
20531 object = nullptr; // silence warning, see #821
20532 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20533 {
20534 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20535 }
20536 break;
20537 }
20538 }
20539 }
20540 
20541 /// constructor for strings
20542 json_value(const string_t& value) : string(create<string_t>(value)) {}
20543 
20544 /// constructor for rvalue strings
20545 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20546 
20547 /// constructor for objects
20548 json_value(const object_t& value) : object(create<object_t>(value)) {}
20549 
20550 /// constructor for rvalue objects
20551 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20552 
20553 /// constructor for arrays
20554 json_value(const array_t& value) : array(create<array_t>(value)) {}
20555 
20556 /// constructor for rvalue arrays
20557 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20558 
20559 /// constructor for binary arrays
20560 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20561 
20562 /// constructor for rvalue binary arrays
20563 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20564 
20565 /// constructor for binary arrays (internal type)
20566 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20567 
20568 /// constructor for rvalue binary arrays (internal type)
20569 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20570 
20571 void destroy(value_t t)
20572 {
20573 if (
20574 (t == value_t::object && object == nullptr) ||
20575 (t == value_t::array && array == nullptr) ||
20576 (t == value_t::string && string == nullptr) ||
20577 (t == value_t::binary && binary == nullptr)
20578 )
20579 {
20580 //not initialized (e.g. due to exception in the ctor)
20581 return;
20582 }
20583 if (t == value_t::array || t == value_t::object)
20584 {
20585 // flatten the current json_value to a heap-allocated stack
20586 std::vector<basic_json> stack;
20587 
20588 // move the top-level items to stack
20589 if (t == value_t::array)
20590 {
20591 stack.reserve(array->size());
20592 std::move(array->begin(), array->end(), std::back_inserter(stack));
20593 }
20594 else
20595 {
20596 stack.reserve(object->size());
20597 for (auto&& it : *object)
20598 {
20599 stack.push_back(std::move(it.second));
20600 }
20601 }
20602 
20603 while (!stack.empty())
20604 {
20605 // move the last item to local variable to be processed
20606 basic_json current_item(std::move(stack.back()));
20607 stack.pop_back();
20608 
20609 // if current_item is array/object, move
20610 // its children to the stack to be processed later
20611 if (current_item.is_array())
20612 {
20613 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20614 
20615 current_item.m_data.m_value.array->clear();
20616 }
20617 else if (current_item.is_object())
20618 {
20619 for (auto&& it : *current_item.m_data.m_value.object)
20620 {
20621 stack.push_back(std::move(it.second));
20622 }
20623 
20624 current_item.m_data.m_value.object->clear();
20625 }
20626 
20627 // it's now safe that current_item get destructed
20628 // since it doesn't have any children
20629 }
20630 }
20631 
20632 switch (t)
20633 {
20634 case value_t::object:
20635 {
20636 AllocatorType<object_t> alloc;
20637 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20638 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20639 break;
20640 }
20641 
20642 case value_t::array:
20643 {
20644 AllocatorType<array_t> alloc;
20645 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20646 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20647 break;
20648 }
20649 
20650 case value_t::string:
20651 {
20652 AllocatorType<string_t> alloc;
20653 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20654 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20655 break;
20656 }
20657 
20658 case value_t::binary:
20659 {
20660 AllocatorType<binary_t> alloc;
20661 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20662 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20663 break;
20664 }
20665 
20666 case value_t::null:
20667 case value_t::boolean:
20668 case value_t::number_integer:
20669 case value_t::number_unsigned:
20670 case value_t::number_float:
20671 case value_t::discarded:
20672 default:
20673 {
20674 break;
20675 }
20676 }
20677 }
20678 };
20679 
20680 private:
20681 /*!
20682 @brief checks the class invariants
20683 
20684 This function asserts the class invariants. It needs to be called at the
20685 end of every constructor to make sure that created objects respect the
20686 invariant. Furthermore, it has to be called each time the type of a JSON
20687 value is changed, because the invariant expresses a relationship between
20688 @a m_type and @a m_value.
20689 
20690 Furthermore, the parent relation is checked for arrays and objects: If
20691 @a check_parents true and the value is an array or object, then the
20692 container's elements must have the current value as parent.
20693 
20694 @param[in] check_parents whether the parent relation should be checked.
20695 The value is true by default and should only be set to false
20696 during destruction of objects when the invariant does not
20697 need to hold.
20698 */
20699 void assert_invariant(bool check_parents = true) const noexcept
20700 {
20701 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20702 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20703 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20704 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20705 
20706#if JSON_DIAGNOSTICS
20707 JSON_TRY
20708 {
20709 // cppcheck-suppress assertWithSideEffect
20710 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20711 {
20712 return j.m_parent == this;
20713 }));
20714 }
20715 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20716#endif
20717 static_cast<void>(check_parents);
20718 }
20719 
20720 void set_parents()
20721 {
20722#if JSON_DIAGNOSTICS
20723 switch (m_data.m_type)
20724 {
20725 case value_t::array:
20726 {
20727 for (auto& element : *m_data.m_value.array)
20728 {
20729 element.m_parent = this;
20730 }
20731 break;
20732 }
20733 
20734 case value_t::object:
20735 {
20736 for (auto& element : *m_data.m_value.object)
20737 {
20738 element.second.m_parent = this;
20739 }
20740 break;
20741 }
20742 
20743 case value_t::null:
20744 case value_t::string:
20745 case value_t::boolean:
20746 case value_t::number_integer:
20747 case value_t::number_unsigned:
20748 case value_t::number_float:
20749 case value_t::binary:
20750 case value_t::discarded:
20751 default:
20752 break;
20753 }
20754#endif
20755 }
20756 
20757 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20758 {
20759#if JSON_DIAGNOSTICS
20760 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20761 {
20762 (it + i)->m_parent = this;
20763 }
20764#else
20765 static_cast<void>(count_set_parents);
20766#endif
20767 return it;
20768 }
20769 
20770 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20771 {
20772#if JSON_DIAGNOSTICS
20773 if (old_capacity != detail::unknown_size())
20774 {
20775 // see https://github.com/nlohmann/json/issues/2838
20776 JSON_ASSERT(type() == value_t::array);
20777 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20778 {
20779 // capacity has changed: update all parents
20780 set_parents();
20781 return j;
20782 }
20783 }
20784 
20785 // ordered_json uses a vector internally, so pointers could have
20786 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20787#ifdef JSON_HEDLEY_MSVC_VERSION
20788#pragma warning(push )
20789#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20790#endif
20791 if (detail::is_ordered_map<object_t>::value)
20792 {
20793 set_parents();
20794 return j;
20795 }
20796#ifdef JSON_HEDLEY_MSVC_VERSION
20797#pragma warning( pop )
20798#endif
20799 
20800 j.m_parent = this;
20801#else
20802 static_cast<void>(j);
20803 static_cast<void>(old_capacity);
20804#endif
20805 return j;
20806 }
20807 
20808 public:
20809 //////////////////////////
20810 // JSON parser callback //
20811 //////////////////////////
20812 
20813 /// @brief parser event types
20814 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20815 using parse_event_t = detail::parse_event_t;
20816 
20817 /// @brief per-element parser callback type
20818 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20819 using parser_callback_t = detail::parser_callback_t<basic_json>;
20820 
20821 //////////////////
20822 // constructors //
20823 //////////////////
20824 
20825 /// @name constructors and destructors
20826 /// Constructors of class @ref basic_json, copy/move constructor, copy
20827 /// assignment, static functions creating objects, and the destructor.
20828 /// @{
20829 
20830 /// @brief create an empty value with a given type
20831 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20832 basic_json(const value_t v)
20833 : m_data(v)
20834 {
20835 assert_invariant();
20836 }
20837 
20838 /// @brief create a null object
20839 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20840 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20841 : basic_json(value_t::null)
20842 {
20843 assert_invariant();
20844 }
20845 
20846 /// @brief create a JSON value from compatible types
20847 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20848 template < typename CompatibleType,
20849 typename U = detail::uncvref_t<CompatibleType>,
20850 detail::enable_if_t <
20851 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20852 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20853 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20854 std::forward<CompatibleType>(val))))
20855 {
20856 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20857 set_parents();
20858 assert_invariant();
20859 }
20860 
20861 /// @brief create a JSON value from an existing one
20862 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20863 template < typename BasicJsonType,
20864 detail::enable_if_t <
20865 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20866 basic_json(const BasicJsonType& val)
20867#if JSON_DIAGNOSTIC_POSITIONS
20868 : start_position(val.start_pos()),
20869 end_position(val.end_pos())
20870#endif
20871 {
20872 using other_boolean_t = typename BasicJsonType::boolean_t;
20873 using other_number_float_t = typename BasicJsonType::number_float_t;
20874 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20875 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20876 using other_string_t = typename BasicJsonType::string_t;
20877 using other_object_t = typename BasicJsonType::object_t;
20878 using other_array_t = typename BasicJsonType::array_t;
20879 using other_binary_t = typename BasicJsonType::binary_t;
20880 
20881 switch (val.type())
20882 {
20883 case value_t::boolean:
20884 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20885 break;
20886 case value_t::number_float:
20887 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20888 break;
20889 case value_t::number_integer:
20890 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20891 break;
20892 case value_t::number_unsigned:
20893 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20894 break;
20895 case value_t::string:
20896 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20897 break;
20898 case value_t::object:
20899 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20900 break;
20901 case value_t::array:
20902 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20903 break;
20904 case value_t::binary:
20905 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20906 break;
20907 case value_t::null:
20908 *this = nullptr;
20909 break;
20910 case value_t::discarded:
20911 m_data.m_type = value_t::discarded;
20912 break;
20913 default: // LCOV_EXCL_LINE
20914 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20915 }
20916 JSON_ASSERT(m_data.m_type == val.type());
20917 
20918 set_parents();
20919 assert_invariant();
20920 }
20921 
20922 /// @brief create a container (array or object) from an initializer list
20923 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20924 basic_json(initializer_list_t init,
20925 bool type_deduction = true,
20926 value_t manual_type = value_t::array)
20927 {
20928 // check if each element is an array with two elements whose first
20929 // element is a string
20930 bool is_an_object = std::all_of(init.begin(), init.end(),
20931 [](const detail::json_ref<basic_json>& element_ref)
20932 {
20933 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20934 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20935 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20936 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20937 });
20938 
20939 // adjust type if type deduction is not wanted
20940 if (!type_deduction)
20941 {
20942 // if array is wanted, do not create an object though possible
20943 if (manual_type == value_t::array)
20944 {
20945 is_an_object = false;
20946 }
20947 
20948 // if object is wanted but impossible, throw an exception
20949 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20950 {
20951 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20952 }
20953 }
20954 
20955 if (is_an_object)
20956 {
20957 // the initializer list is a list of pairs -> create object
20958 m_data.m_type = value_t::object;
20959 m_data.m_value = value_t::object;
20960 
20961 for (auto& element_ref : init)
20962 {
20963 auto element = element_ref.moved_or_copied();
20964 m_data.m_value.object->emplace(
20965 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20966 std::move((*element.m_data.m_value.array)[1]));
20967 }
20968 }
20969 else
20970 {
20971 // the initializer list describes an array -> create array
20972 m_data.m_type = value_t::array;
20973 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20974 }
20975 
20976 set_parents();
20977 assert_invariant();
20978 }
20979 
20980 /// @brief explicitly create a binary array (without subtype)
20981 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20982 JSON_HEDLEY_WARN_UNUSED_RESULT
20983 static basic_json binary(const typename binary_t::container_type& init)
20984 {
20985 auto res = basic_json();
20986 res.m_data.m_type = value_t::binary;
20987 res.m_data.m_value = init;
20988 return res;
20989 }
20990 
20991 /// @brief explicitly create a binary array (with subtype)
20992 /// @sa https://json.nlohmann.me/api/basic_json/binary/
20993 JSON_HEDLEY_WARN_UNUSED_RESULT
20994 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20995 {
20996 auto res = basic_json();
20997 res.m_data.m_type = value_t::binary;
20998 res.m_data.m_value = binary_t(init, subtype);
20999 return res;
21000 }
21001 
21002 /// @brief explicitly create a binary array
21003 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21004 JSON_HEDLEY_WARN_UNUSED_RESULT
21005 static basic_json binary(typename binary_t::container_type&& init)
21006 {
21007 auto res = basic_json();
21008 res.m_data.m_type = value_t::binary;
21009 res.m_data.m_value = std::move(init);
21010 return res;
21011 }
21012 
21013 /// @brief explicitly create a binary array (with subtype)
21014 /// @sa https://json.nlohmann.me/api/basic_json/binary/
21015 JSON_HEDLEY_WARN_UNUSED_RESULT
21016 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21017 {
21018 auto res = basic_json();
21019 res.m_data.m_type = value_t::binary;
21020 res.m_data.m_value = binary_t(std::move(init), subtype);
21021 return res;
21022 }
21023 
21024 /// @brief explicitly create an array from an initializer list
21025 /// @sa https://json.nlohmann.me/api/basic_json/array/
21026 JSON_HEDLEY_WARN_UNUSED_RESULT
21027 static basic_json array(initializer_list_t init = {})
21028 {
21029 return basic_json(init, false, value_t::array);
21030 }
21031 
21032 /// @brief explicitly create an object from an initializer list
21033 /// @sa https://json.nlohmann.me/api/basic_json/object/
21034 JSON_HEDLEY_WARN_UNUSED_RESULT
21035 static basic_json object(initializer_list_t init = {})
21036 {
21037 return basic_json(init, false, value_t::object);
21038 }
21039 
21040 /// @brief construct an array with count copies of given value
21041 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21042 basic_json(size_type cnt, const basic_json& val):
21043 m_data{cnt, val}
21044 {
21045 set_parents();
21046 assert_invariant();
21047 }
21048 
21049 /// @brief construct a JSON container given an iterator range
21050 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21051 template < class InputIT, typename std::enable_if <
21052 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21053 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21054 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21055 {
21056 JSON_ASSERT(first.m_object != nullptr);
21057 JSON_ASSERT(last.m_object != nullptr);
21058 
21059 // make sure iterator fits the current value
21060 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21061 {
21062 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21063 }
21064 
21065 // copy type from first iterator
21066 m_data.m_type = first.m_object->m_data.m_type;
21067 
21068 // check if iterator range is complete for primitive values
21069 switch (m_data.m_type)
21070 {
21071 case value_t::boolean:
21072 case value_t::number_float:
21073 case value_t::number_integer:
21074 case value_t::number_unsigned:
21075 case value_t::string:
21076 {
21077 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21078 || !last.m_it.primitive_iterator.is_end()))
21079 {
21080 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21081 }
21082 break;
21083 }
21084 
21085 case value_t::null:
21086 case value_t::object:
21087 case value_t::array:
21088 case value_t::binary:
21089 case value_t::discarded:
21090 default:
21091 break;
21092 }
21093 
21094 switch (m_data.m_type)
21095 {
21096 case value_t::number_integer:
21097 {
21098 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21099 break;
21100 }
21101 
21102 case value_t::number_unsigned:
21103 {
21104 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21105 break;
21106 }
21107 
21108 case value_t::number_float:
21109 {
21110 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21111 break;
21112 }
21113 
21114 case value_t::boolean:
21115 {
21116 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21117 break;
21118 }
21119 
21120 case value_t::string:
21121 {
21122 m_data.m_value = *first.m_object->m_data.m_value.string;
21123 break;
21124 }
21125 
21126 case value_t::object:
21127 {
21128 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21129 last.m_it.object_iterator);
21130 break;
21131 }
21132 
21133 case value_t::array:
21134 {
21135 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21136 last.m_it.array_iterator);
21137 break;
21138 }
21139 
21140 case value_t::binary:
21141 {
21142 m_data.m_value = *first.m_object->m_data.m_value.binary;
21143 break;
21144 }
21145 
21146 case value_t::null:
21147 case value_t::discarded:
21148 default:
21149 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21150 }
21151 
21152 set_parents();
21153 assert_invariant();
21154 }
21155 
21156 ///////////////////////////////////////
21157 // other constructors and destructor //
21158 ///////////////////////////////////////
21159 
21160 template<typename JsonRef,
21161 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
21162 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21163 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21164 
21165 /// @brief copy constructor
21166 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21167 basic_json(const basic_json& other)
21168 : json_base_class_t(other)
21169#if JSON_DIAGNOSTIC_POSITIONS
21170 , start_position(other.start_position)
21171 , end_position(other.end_position)
21172#endif
21173 {
21174 m_data.m_type = other.m_data.m_type;
21175 // check of passed value is valid
21176 other.assert_invariant();
21177 
21178 switch (m_data.m_type)
21179 {
21180 case value_t::object:
21181 {
21182 m_data.m_value = *other.m_data.m_value.object;
21183 break;
21184 }
21185 
21186 case value_t::array:
21187 {
21188 m_data.m_value = *other.m_data.m_value.array;
21189 break;
21190 }
21191 
21192 case value_t::string:
21193 {
21194 m_data.m_value = *other.m_data.m_value.string;
21195 break;
21196 }
21197 
21198 case value_t::boolean:
21199 {
21200 m_data.m_value = other.m_data.m_value.boolean;
21201 break;
21202 }
21203 
21204 case value_t::number_integer:
21205 {
21206 m_data.m_value = other.m_data.m_value.number_integer;
21207 break;
21208 }
21209 
21210 case value_t::number_unsigned:
21211 {
21212 m_data.m_value = other.m_data.m_value.number_unsigned;
21213 break;
21214 }
21215 
21216 case value_t::number_float:
21217 {
21218 m_data.m_value = other.m_data.m_value.number_float;
21219 break;
21220 }
21221 
21222 case value_t::binary:
21223 {
21224 m_data.m_value = *other.m_data.m_value.binary;
21225 break;
21226 }
21227 
21228 case value_t::null:
21229 case value_t::discarded:
21230 default:
21231 break;
21232 }
21233 
21234 set_parents();
21235 assert_invariant();
21236 }
21237 
21238 /// @brief move constructor
21239 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21240 basic_json(basic_json&& other) noexcept
21241 : json_base_class_t(std::forward<json_base_class_t>(other)),
21242 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21243#if JSON_DIAGNOSTIC_POSITIONS
21244 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21245 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21246#endif
21247 {
21248 // check that passed value is valid
21249 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21250 
21251 // invalidate payload
21252 other.m_data.m_type = value_t::null;
21253 other.m_data.m_value = {};
21254 
21255#if JSON_DIAGNOSTIC_POSITIONS
21256 other.start_position = std::string::npos;
21257 other.end_position = std::string::npos;
21258#endif
21259 
21260 set_parents();
21261 assert_invariant();
21262 }
21263 
21264 /// @brief copy assignment
21265 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
21266 basic_json& operator=(basic_json other) noexcept (
21267 std::is_nothrow_move_constructible<value_t>::value&&
21268 std::is_nothrow_move_assignable<value_t>::value&&
21269 std::is_nothrow_move_constructible<json_value>::value&&
21270 std::is_nothrow_move_assignable<json_value>::value&&
21271 std::is_nothrow_move_assignable<json_base_class_t>::value
21272 )
21273 {
21274 // check that passed value is valid
21275 other.assert_invariant();
21276 
21277 using std::swap;
21278 swap(m_data.m_type, other.m_data.m_type);
21279 swap(m_data.m_value, other.m_data.m_value);
21280 
21281#if JSON_DIAGNOSTIC_POSITIONS
21282 swap(start_position, other.start_position);
21283 swap(end_position, other.end_position);
21284#endif
21285 
21286 json_base_class_t::operator=(std::move(other));
21287 
21288 set_parents();
21289 assert_invariant();
21290 return *this;
21291 }
21292 
21293 /// @brief destructor
21294 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
21295 ~basic_json() noexcept
21296 {
21297 assert_invariant(false);
21298 }
21299 
21300 /// @}
21301 
21302 public:
21303 ///////////////////////
21304 // object inspection //
21305 ///////////////////////
21306 
21307 /// @name object inspection
21308 /// Functions to inspect the type of a JSON value.
21309 /// @{
21310 
21311 /// @brief serialization
21312 /// @sa https://json.nlohmann.me/api/basic_json/dump/
21313 string_t dump(const int indent = -1,
21314 const char indent_char = ' ',
21315 const bool ensure_ascii = false,
21316 const error_handler_t error_handler = error_handler_t::strict) const
21317 {
21318 string_t result;
21319 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21320 
21321 if (indent >= 0)
21322 {
21323 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21324 }
21325 else
21326 {
21327 s.dump(*this, false, ensure_ascii, 0);
21328 }
21329 
21330 return result;
21331 }
21332 
21333 /// @brief return the type of the JSON value (explicit)
21334 /// @sa https://json.nlohmann.me/api/basic_json/type/
21335 constexpr value_t type() const noexcept
21336 {
21337 return m_data.m_type;
21338 }
21339 
21340 /// @brief return whether type is primitive
21341 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
21342 constexpr bool is_primitive() const noexcept
21343 {
21344 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21345 }
21346 
21347 /// @brief return whether type is structured
21348 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
21349 constexpr bool is_structured() const noexcept
21350 {
21351 return is_array() || is_object();
21352 }
21353 
21354 /// @brief return whether value is null
21355 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
21356 constexpr bool is_null() const noexcept
21357 {
21358 return m_data.m_type == value_t::null;
21359 }
21360 
21361 /// @brief return whether value is a boolean
21362 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
21363 constexpr bool is_boolean() const noexcept
21364 {
21365 return m_data.m_type == value_t::boolean;
21366 }
21367 
21368 /// @brief return whether value is a number
21369 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
21370 constexpr bool is_number() const noexcept
21371 {
21372 return is_number_integer() || is_number_float();
21373 }
21374 
21375 /// @brief return whether value is an integer number
21376 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
21377 constexpr bool is_number_integer() const noexcept
21378 {
21379 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21380 }
21381 
21382 /// @brief return whether value is an unsigned integer number
21383 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
21384 constexpr bool is_number_unsigned() const noexcept
21385 {
21386 return m_data.m_type == value_t::number_unsigned;
21387 }
21388 
21389 /// @brief return whether value is a floating-point number
21390 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
21391 constexpr bool is_number_float() const noexcept
21392 {
21393 return m_data.m_type == value_t::number_float;
21394 }
21395 
21396 /// @brief return whether value is an object
21397 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
21398 constexpr bool is_object() const noexcept
21399 {
21400 return m_data.m_type == value_t::object;
21401 }
21402 
21403 /// @brief return whether value is an array
21404 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
21405 constexpr bool is_array() const noexcept
21406 {
21407 return m_data.m_type == value_t::array;
21408 }
21409 
21410 /// @brief return whether value is a string
21411 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
21412 constexpr bool is_string() const noexcept
21413 {
21414 return m_data.m_type == value_t::string;
21415 }
21416 
21417 /// @brief return whether value is a binary array
21418 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
21419 constexpr bool is_binary() const noexcept
21420 {
21421 return m_data.m_type == value_t::binary;
21422 }
21423 
21424 /// @brief return whether value is discarded
21425 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
21426 constexpr bool is_discarded() const noexcept
21427 {
21428 return m_data.m_type == value_t::discarded;
21429 }
21430 
21431 /// @brief return the type of the JSON value (implicit)
21432 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
21433 constexpr operator value_t() const noexcept
21434 {
21435 return m_data.m_type;
21436 }
21437 
21438 /// @}
21439 
21440 private:
21441 //////////////////
21442 // value access //
21443 //////////////////
21444 
21445 /// get a boolean (explicit)
21446 boolean_t get_impl(boolean_t* /*unused*/) const
21447 {
21448 if (JSON_HEDLEY_LIKELY(is_boolean()))
21449 {
21450 return m_data.m_value.boolean;
21451 }
21452 
21453 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21454 }
21455 
21456 /// get a pointer to the value (object)
21457 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21458 {
21459 return is_object() ? m_data.m_value.object : nullptr;
21460 }
21461 
21462 /// get a pointer to the value (object)
21463 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21464 {
21465 return is_object() ? m_data.m_value.object : nullptr;
21466 }
21467 
21468 /// get a pointer to the value (array)
21469 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21470 {
21471 return is_array() ? m_data.m_value.array : nullptr;
21472 }
21473 
21474 /// get a pointer to the value (array)
21475 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21476 {
21477 return is_array() ? m_data.m_value.array : nullptr;
21478 }
21479 
21480 /// get a pointer to the value (string)
21481 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21482 {
21483 return is_string() ? m_data.m_value.string : nullptr;
21484 }
21485 
21486 /// get a pointer to the value (string)
21487 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21488 {
21489 return is_string() ? m_data.m_value.string : nullptr;
21490 }
21491 
21492 /// get a pointer to the value (boolean)
21493 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21494 {
21495 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21496 }
21497 
21498 /// get a pointer to the value (boolean)
21499 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21500 {
21501 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21502 }
21503 
21504 /// get a pointer to the value (integer number)
21505 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21506 {
21507 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21508 }
21509 
21510 /// get a pointer to the value (integer number)
21511 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21512 {
21513 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21514 }
21515 
21516 /// get a pointer to the value (unsigned number)
21517 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21518 {
21519 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21520 }
21521 
21522 /// get a pointer to the value (unsigned number)
21523 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21524 {
21525 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21526 }
21527 
21528 /// get a pointer to the value (floating-point number)
21529 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21530 {
21531 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21532 }
21533 
21534 /// get a pointer to the value (floating-point number)
21535 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21536 {
21537 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21538 }
21539 
21540 /// get a pointer to the value (binary)
21541 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21542 {
21543 return is_binary() ? m_data.m_value.binary : nullptr;
21544 }
21545 
21546 /// get a pointer to the value (binary)
21547 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21548 {
21549 return is_binary() ? m_data.m_value.binary : nullptr;
21550 }
21551 
21552 /*!
21553 @brief helper function to implement get_ref()
21554 
21555 This function helps to implement get_ref() without code duplication for
21556 const and non-const overloads
21557 
21558 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
21559 
21560 @throw type_error.303 if ReferenceType does not match underlying value
21561 type of the current JSON
21562 */
21563 template<typename ReferenceType, typename ThisType>
21564 static ReferenceType get_ref_impl(ThisType& obj)
21565 {
21566 // delegate the call to get_ptr<>()
21567 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21568 
21569 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21570 {
21571 return *ptr;
21572 }
21573 
21574 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21575 }
21576 
21577 public:
21578 /// @name value access
21579 /// Direct access to the stored value of a JSON value.
21580 /// @{
21581 
21582 /// @brief get a pointer value (implicit)
21583 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21584 template<typename PointerType, typename std::enable_if<
21585 std::is_pointer<PointerType>::value, int>::type = 0>
21586 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21587 {
21588 // delegate the call to get_impl_ptr<>()
21589 return get_impl_ptr(static_cast<PointerType>(nullptr));
21590 }
21591 
21592 /// @brief get a pointer value (implicit)
21593 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21594 template < typename PointerType, typename std::enable_if <
21595 std::is_pointer<PointerType>::value&&
21596 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21597 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21598 {
21599 // delegate the call to get_impl_ptr<>() const
21600 return get_impl_ptr(static_cast<PointerType>(nullptr));
21601 }
21602 
21603 private:
21604 /*!
21605 @brief get a value (explicit)
21606 
21607 Explicit type conversion between the JSON value and a compatible value
21608 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21609 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21610 The value is converted by calling the @ref json_serializer<ValueType>
21611 `from_json()` method.
21612 
21613 The function is equivalent to executing
21614 @code {.cpp}
21615 ValueType ret;
21616 JSONSerializer<ValueType>::from_json(*this, ret);
21617 return ret;
21618 @endcode
21619 
21620 This overloads is chosen if:
21621 - @a ValueType is not @ref basic_json,
21622 - @ref json_serializer<ValueType> has a `from_json()` method of the form
21623 `void from_json(const basic_json&, ValueType&)`, and
21624 - @ref json_serializer<ValueType> does not have a `from_json()` method of
21625 the form `ValueType from_json(const basic_json&)`
21626 
21627 @tparam ValueType the returned value type
21628 
21629 @return copy of the JSON value, converted to @a ValueType
21630 
21631 @throw what @ref json_serializer<ValueType> `from_json()` method throws
21632 
21633 @liveexample{The example below shows several conversions from JSON values
21634 to other types. There a few things to note: (1) Floating-point numbers can
21635 be converted to integers\, (2) A JSON array can be converted to a standard
21636 `std::vector<short>`\, (3) A JSON object can be converted to C++
21637 associative containers such as `std::unordered_map<std::string\,
21638 json>`.,get__ValueType_const}
21639 
21640 @since version 2.1.0
21641 */
21642 template < typename ValueType,
21643 detail::enable_if_t <
21644 detail::is_default_constructible<ValueType>::value&&
21645 detail::has_from_json<basic_json_t, ValueType>::value,
21646 int > = 0 >
21647 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21648 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21649 {
21650 auto ret = ValueType();
21651 JSONSerializer<ValueType>::from_json(*this, ret);
21652 return ret;
21653 }
21654 
21655 /*!
21656 @brief get a value (explicit); special case
21657 
21658 Explicit type conversion between the JSON value and a compatible value
21659 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21660 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21661 The value is converted by calling the @ref json_serializer<ValueType>
21662 `from_json()` method.
21663 
21664 The function is equivalent to executing
21665 @code {.cpp}
21666 return JSONSerializer<ValueType>::from_json(*this);
21667 @endcode
21668 
21669 This overloads is chosen if:
21670 - @a ValueType is not @ref basic_json and
21671 - @ref json_serializer<ValueType> has a `from_json()` method of the form
21672 `ValueType from_json(const basic_json&)`
21673 
21674 @note If @ref json_serializer<ValueType> has both overloads of
21675 `from_json()`, this one is chosen.
21676 
21677 @tparam ValueType the returned value type
21678 
21679 @return copy of the JSON value, converted to @a ValueType
21680 
21681 @throw what @ref json_serializer<ValueType> `from_json()` method throws
21682 
21683 @since version 2.1.0
21684 */
21685 template < typename ValueType,
21686 detail::enable_if_t <
21687 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21688 int > = 0 >
21689 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21690 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21691 {
21692 return JSONSerializer<ValueType>::from_json(*this);
21693 }
21694 
21695 /*!
21696 @brief get special-case overload
21697 
21698 This overloads converts the current @ref basic_json in a different
21699 @ref basic_json type
21700 
21701 @tparam BasicJsonType == @ref basic_json
21702 
21703 @return a copy of *this, converted into @a BasicJsonType
21704 
21705 @complexity Depending on the implementation of the called `from_json()`
21706 method.
21707 
21708 @since version 3.2.0
21709 */
21710 template < typename BasicJsonType,
21711 detail::enable_if_t <
21712 detail::is_basic_json<BasicJsonType>::value,
21713 int > = 0 >
21714 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21715 {
21716 return *this;
21717 }
21718 
21719 /*!
21720 @brief get special-case overload
21721 
21722 This overloads avoids a lot of template boilerplate, it can be seen as the
21723 identity method
21724 
21725 @tparam BasicJsonType == @ref basic_json
21726 
21727 @return a copy of *this
21728 
21729 @complexity Constant.
21730 
21731 @since version 2.1.0
21732 */
21733 template<typename BasicJsonType,
21734 detail::enable_if_t<
21735 std::is_same<BasicJsonType, basic_json_t>::value,
21736 int> = 0>
21737 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21738 {
21739 return *this;
21740 }
21741 
21742 /*!
21743 @brief get a pointer value (explicit)
21744 @copydoc get()
21745 */
21746 template<typename PointerType,
21747 detail::enable_if_t<
21748 std::is_pointer<PointerType>::value,
21749 int> = 0>
21750 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21751 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21752 {
21753 // delegate the call to get_ptr
21754 return get_ptr<PointerType>();
21755 }
21756 
21757 public:
21758 /*!
21759 @brief get a (pointer) value (explicit)
21760 
21761 Performs explicit type conversion between the JSON value and a compatible value if required.
21762 
21763 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
21764 No copies are made.
21765 
21766 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
21767 from the current @ref basic_json.
21768 
21769 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
21770 method.
21771 
21772 @tparam ValueTypeCV the provided value type
21773 @tparam ValueType the returned value type
21774 
21775 @return copy of the JSON value, converted to @tparam ValueType if necessary
21776 
21777 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
21778 
21779 @since version 2.1.0
21780 */
21781 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21782#if defined(JSON_HAS_CPP_14)
21783 constexpr
21784#endif
21785 auto get() const noexcept(
21786 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21787 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21788 {
21789 // we cannot static_assert on ValueTypeCV being non-const, because
21790 // there is support for get<const basic_json_t>(), which is why we
21791 // still need the uncvref
21792 static_assert(!std::is_reference<ValueTypeCV>::value,
21793 "get() cannot be used with reference types, you might want to use get_ref()");
21794 return get_impl<ValueType>(detail::priority_tag<4> {});
21795 }
21796 
21797 /*!
21798 @brief get a pointer value (explicit)
21799 
21800 Explicit pointer access to the internally stored JSON value. No copies are
21801 made.
21802 
21803 @warning The pointer becomes invalid if the underlying JSON object
21804 changes.
21805 
21806 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
21807 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
21808 @ref number_unsigned_t, or @ref number_float_t.
21809 
21810 @return pointer to the internally stored JSON value if the requested
21811 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
21812 
21813 @complexity Constant.
21814 
21815 @liveexample{The example below shows how pointers to internal values of a
21816 JSON value can be requested. Note that no type conversions are made and a
21817 `nullptr` is returned if the value and the requested pointer type does not
21818 match.,get__PointerType}
21819 
21820 @sa see @ref get_ptr() for explicit pointer-member access
21821 
21822 @since version 1.0.0
21823 */
21824 template<typename PointerType, typename std::enable_if<
21825 std::is_pointer<PointerType>::value, int>::type = 0>
21826 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21827 {
21828 // delegate the call to get_ptr
21829 return get_ptr<PointerType>();
21830 }
21831 
21832 /// @brief get a value (explicit)
21833 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
21834 template < typename ValueType,
21835 detail::enable_if_t <
21836 !detail::is_basic_json<ValueType>::value&&
21837 detail::has_from_json<basic_json_t, ValueType>::value,
21838 int > = 0 >
21839 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21840 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21841 {
21842 JSONSerializer<ValueType>::from_json(*this, v);
21843 return v;
21844 }
21845 
21846 // specialization to allow calling get_to with a basic_json value
21847 // see https://github.com/nlohmann/json/issues/2175
21848 template<typename ValueType,
21849 detail::enable_if_t <
21850 detail::is_basic_json<ValueType>::value,
21851 int> = 0>
21852 ValueType & get_to(ValueType& v) const
21853 {
21854 v = *this;
21855 return v;
21856 }
21857 
21858 template <
21859 typename T, std::size_t N,
21860 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21861 detail::enable_if_t <
21862 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21863 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21864 noexcept(noexcept(JSONSerializer<Array>::from_json(
21865 std::declval<const basic_json_t&>(), v)))
21866 {
21867 JSONSerializer<Array>::from_json(*this, v);
21868 return v;
21869 }
21870 
21871 /// @brief get a reference value (implicit)
21872 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21873 template<typename ReferenceType, typename std::enable_if<
21874 std::is_reference<ReferenceType>::value, int>::type = 0>
21875 ReferenceType get_ref()
21876 {
21877 // delegate call to get_ref_impl
21878 return get_ref_impl<ReferenceType>(*this);
21879 }
21880 
21881 /// @brief get a reference value (implicit)
21882 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21883 template < typename ReferenceType, typename std::enable_if <
21884 std::is_reference<ReferenceType>::value&&
21885 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21886 ReferenceType get_ref() const
21887 {
21888 // delegate call to get_ref_impl
21889 return get_ref_impl<ReferenceType>(*this);
21890 }
21891 
21892 /*!
21893 @brief get a value (implicit)
21894 
21895 Implicit type conversion between the JSON value and a compatible value.
21896 The call is realized by calling @ref get() const.
21897 
21898 @tparam ValueType non-pointer type compatible to the JSON value, for
21899 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21900 `std::vector` types for JSON arrays. The character type of @ref string_t
21901 as well as an initializer list of this type is excluded to avoid
21902 ambiguities as these types implicitly convert to `std::string`.
21903 
21904 @return copy of the JSON value, converted to type @a ValueType
21905 
21906 @throw type_error.302 in case passed type @a ValueType is incompatible
21907 to the JSON value type (e.g., the JSON value is of type boolean, but a
21908 string is requested); see example below
21909 
21910 @complexity Linear in the size of the JSON value.
21911 
21912 @liveexample{The example below shows several conversions from JSON values
21913 to other types. There a few things to note: (1) Floating-point numbers can
21914 be converted to integers\, (2) A JSON array can be converted to a standard
21915 `std::vector<short>`\, (3) A JSON object can be converted to C++
21916 associative containers such as `std::unordered_map<std::string\,
21917 json>`.,operator__ValueType}
21918 
21919 @since version 1.0.0
21920 */
21921 template < typename ValueType, typename std::enable_if <
21922 detail::conjunction <
21923 detail::negation<std::is_pointer<ValueType>>,
21924 detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21925 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21926 detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21927 detail::negation<detail::is_basic_json<ValueType>>,
21928 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21929#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21930 detail::negation<std::is_same<ValueType, std::string_view>>,
21931#endif
21932#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21933 detail::negation<std::is_same<ValueType, std::any>>,
21934#endif
21935 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21936 >::value, int >::type = 0 >
21937 JSON_EXPLICIT operator ValueType() const
21938 {
21939 // delegate the call to get<>() const
21940 return get<ValueType>();
21941 }
21942 
21943 /// @brief get a binary value
21944 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21945 binary_t& get_binary()
21946 {
21947 if (!is_binary())
21948 {
21949 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21950 }
21951 
21952 return *get_ptr<binary_t*>();
21953 }
21954 
21955 /// @brief get a binary value
21956 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21957 const binary_t& get_binary() const
21958 {
21959 if (!is_binary())
21960 {
21961 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21962 }
21963 
21964 return *get_ptr<const binary_t*>();
21965 }
21966 
21967 /// @}
21968 
21969 ////////////////////
21970 // element access //
21971 ////////////////////
21972 
21973 /// @name element access
21974 /// Access to the JSON value.
21975 /// @{
21976 
21977 /// @brief access specified array element with bounds checking
21978 /// @sa https://json.nlohmann.me/api/basic_json/at/
21979 reference at(size_type idx)
21980 {
21981 // at only works for arrays
21982 if (JSON_HEDLEY_LIKELY(is_array()))
21983 {
21984 JSON_TRY
21985 {
21986 return set_parent(m_data.m_value.array->at(idx));
21987 }
21988 JSON_CATCH (std::out_of_range&)
21989 {
21990 // create better exception explanation
21991 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21992 } // cppcheck-suppress[missingReturn]
21993 }
21994 else
21995 {
21996 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21997 }
21998 }
21999 
22000 /// @brief access specified array element with bounds checking
22001 /// @sa https://json.nlohmann.me/api/basic_json/at/
22002 const_reference at(size_type idx) const
22003 {
22004 // at only works for arrays
22005 if (JSON_HEDLEY_LIKELY(is_array()))
22006 {
22007 JSON_TRY
22008 {
22009 return m_data.m_value.array->at(idx);
22010 }
22011 JSON_CATCH (std::out_of_range&)
22012 {
22013 // create better exception explanation
22014 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22015 } // cppcheck-suppress[missingReturn]
22016 }
22017 else
22018 {
22019 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22020 }
22021 }
22022 
22023 /// @brief access specified object element with bounds checking
22024 /// @sa https://json.nlohmann.me/api/basic_json/at/
22025 reference at(const typename object_t::key_type& key)
22026 {
22027 // at only works for objects
22028 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22029 {
22030 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22031 }
22032 
22033 auto it = m_data.m_value.object->find(key);
22034 if (it == m_data.m_value.object->end())
22035 {
22036 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22037 }
22038 return set_parent(it->second);
22039 }
22040 
22041 /// @brief access specified object element with bounds checking
22042 /// @sa https://json.nlohmann.me/api/basic_json/at/
22043 template<class KeyType, detail::enable_if_t<
22044 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22045 reference at(KeyType && key)
22046 {
22047 // at only works for objects
22048 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22049 {
22050 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22051 }
22052 
22053 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22054 if (it == m_data.m_value.object->end())
22055 {
22056 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22057 }
22058 return set_parent(it->second);
22059 }
22060 
22061 /// @brief access specified object element with bounds checking
22062 /// @sa https://json.nlohmann.me/api/basic_json/at/
22063 const_reference at(const typename object_t::key_type& key) const
22064 {
22065 // at only works for objects
22066 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22067 {
22068 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22069 }
22070 
22071 auto it = m_data.m_value.object->find(key);
22072 if (it == m_data.m_value.object->end())
22073 {
22074 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22075 }
22076 return it->second;
22077 }
22078 
22079 /// @brief access specified object element with bounds checking
22080 /// @sa https://json.nlohmann.me/api/basic_json/at/
22081 template<class KeyType, detail::enable_if_t<
22082 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22083 const_reference at(KeyType && key) const
22084 {
22085 // at only works for objects
22086 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22087 {
22088 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22089 }
22090 
22091 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22092 if (it == m_data.m_value.object->end())
22093 {
22094 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22095 }
22096 return it->second;
22097 }
22098 
22099 /// @brief access specified array element
22100 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22101 reference operator[](size_type idx)
22102 {
22103 // implicitly convert null value to an empty array
22104 if (is_null())
22105 {
22106 m_data.m_type = value_t::array;
22107 m_data.m_value.array = create<array_t>();
22108 assert_invariant();
22109 }
22110 
22111 // operator[] only works for arrays
22112 if (JSON_HEDLEY_LIKELY(is_array()))
22113 {
22114 // fill up array with null values if given idx is outside range
22115 if (idx >= m_data.m_value.array->size())
22116 {
22117#if JSON_DIAGNOSTICS
22118 // remember array size & capacity before resizing
22119 const auto old_size = m_data.m_value.array->size();
22120 const auto old_capacity = m_data.m_value.array->capacity();
22121#endif
22122 m_data.m_value.array->resize(idx + 1);
22123 
22124#if JSON_DIAGNOSTICS
22125 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22126 {
22127 // capacity has changed: update all parents
22128 set_parents();
22129 }
22130 else
22131 {
22132 // set parent for values added above
22133 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22134 }
22135#endif
22136 assert_invariant();
22137 }
22138 
22139 return m_data.m_value.array->operator[](idx);
22140 }
22141 
22142 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22143 }
22144 
22145 /// @brief access specified array element
22146 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22147 const_reference operator[](size_type idx) const
22148 {
22149 // const operator[] only works for arrays
22150 if (JSON_HEDLEY_LIKELY(is_array()))
22151 {
22152 return m_data.m_value.array->operator[](idx);
22153 }
22154 
22155 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22156 }
22157 
22158 /// @brief access specified object element
22159 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22160 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22161 {
22162 // implicitly convert null value to an empty object
22163 if (is_null())
22164 {
22165 m_data.m_type = value_t::object;
22166 m_data.m_value.object = create<object_t>();
22167 assert_invariant();
22168 }
22169 
22170 // operator[] only works for objects
22171 if (JSON_HEDLEY_LIKELY(is_object()))
22172 {
22173 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22174 return set_parent(result.first->second);
22175 }
22176 
22177 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22178 }
22179 
22180 /// @brief access specified object element
22181 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22182 const_reference operator[](const typename object_t::key_type& key) const
22183 {
22184 // const operator[] only works for objects
22185 if (JSON_HEDLEY_LIKELY(is_object()))
22186 {
22187 auto it = m_data.m_value.object->find(key);
22188 JSON_ASSERT(it != m_data.m_value.object->end());
22189 return it->second;
22190 }
22191 
22192 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22193 }
22194 
22195 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22196 // (they seemingly cannot be constrained to resolve the ambiguity)
22197 template<typename T>
22198 reference operator[](T* key)
22199 {
22200 return operator[](typename object_t::key_type(key));
22201 }
22202 
22203 template<typename T>
22204 const_reference operator[](T* key) const
22205 {
22206 return operator[](typename object_t::key_type(key));
22207 }
22208 
22209 /// @brief access specified object element
22210 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22211 template<class KeyType, detail::enable_if_t<
22212 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22213 reference operator[](KeyType && key)
22214 {
22215 // implicitly convert null value to an empty object
22216 if (is_null())
22217 {
22218 m_data.m_type = value_t::object;
22219 m_data.m_value.object = create<object_t>();
22220 assert_invariant();
22221 }
22222 
22223 // operator[] only works for objects
22224 if (JSON_HEDLEY_LIKELY(is_object()))
22225 {
22226 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22227 return set_parent(result.first->second);
22228 }
22229 
22230 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22231 }
22232 
22233 /// @brief access specified object element
22234 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22235 template<class KeyType, detail::enable_if_t<
22236 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22237 const_reference operator[](KeyType && key) const
22238 {
22239 // const operator[] only works for objects
22240 if (JSON_HEDLEY_LIKELY(is_object()))
22241 {
22242 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22243 JSON_ASSERT(it != m_data.m_value.object->end());
22244 return it->second;
22245 }
22246 
22247 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22248 }
22249 
22250 private:
22251 template<typename KeyType>
22252 using is_comparable_with_object_key = detail::is_comparable <
22253 object_comparator_t, const typename object_t::key_type&, KeyType >;
22254 
22255 template<typename ValueType>
22256 using value_return_type = std::conditional <
22257 detail::is_c_string_uncvref<ValueType>::value,
22258 string_t, typename std::decay<ValueType>::type >;
22259 
22260 public:
22261 /// @brief access specified object element with default value
22262 /// @sa https://json.nlohmann.me/api/basic_json/value/
22263 template < class ValueType, detail::enable_if_t <
22264 !detail::is_transparent<object_comparator_t>::value
22265 && detail::is_getable<basic_json_t, ValueType>::value
22266 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22267 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22268 {
22269 // value only works for objects
22270 if (JSON_HEDLEY_LIKELY(is_object()))
22271 {
22272 // if key is found, return value and given default value otherwise
22273 const auto it = find(key);
22274 if (it != end())
22275 {
22276 return it->template get<ValueType>();
22277 }
22278 
22279 return default_value;
22280 }
22281 
22282 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22283 }
22284 
22285 /// @brief access specified object element with default value
22286 /// @sa https://json.nlohmann.me/api/basic_json/value/
22287 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22288 detail::enable_if_t <
22289 !detail::is_transparent<object_comparator_t>::value
22290 && detail::is_getable<basic_json_t, ReturnType>::value
22291 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22292 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22293 {
22294 // value only works for objects
22295 if (JSON_HEDLEY_LIKELY(is_object()))
22296 {
22297 // if key is found, return value and given default value otherwise
22298 const auto it = find(key);
22299 if (it != end())
22300 {
22301 return it->template get<ReturnType>();
22302 }
22303 
22304 return std::forward<ValueType>(default_value);
22305 }
22306 
22307 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22308 }
22309 
22310 /// @brief access specified object element with default value
22311 /// @sa https://json.nlohmann.me/api/basic_json/value/
22312 template < class ValueType, class KeyType, detail::enable_if_t <
22313 detail::is_transparent<object_comparator_t>::value
22314 && !detail::is_json_pointer<KeyType>::value
22315 && is_comparable_with_object_key<KeyType>::value
22316 && detail::is_getable<basic_json_t, ValueType>::value
22317 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22318 ValueType value(KeyType && key, const ValueType& default_value) const
22319 {
22320 // value only works for objects
22321 if (JSON_HEDLEY_LIKELY(is_object()))
22322 {
22323 // if key is found, return value and given default value otherwise
22324 const auto it = find(std::forward<KeyType>(key));
22325 if (it != end())
22326 {
22327 return it->template get<ValueType>();
22328 }
22329 
22330 return default_value;
22331 }
22332 
22333 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22334 }
22335 
22336 /// @brief access specified object element via JSON Pointer with default value
22337 /// @sa https://json.nlohmann.me/api/basic_json/value/
22338 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22339 detail::enable_if_t <
22340 detail::is_transparent<object_comparator_t>::value
22341 && !detail::is_json_pointer<KeyType>::value
22342 && is_comparable_with_object_key<KeyType>::value
22343 && detail::is_getable<basic_json_t, ReturnType>::value
22344 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22345 ReturnType value(KeyType && key, ValueType && default_value) const
22346 {
22347 // value only works for objects
22348 if (JSON_HEDLEY_LIKELY(is_object()))
22349 {
22350 // if key is found, return value and given default value otherwise
22351 const auto it = find(std::forward<KeyType>(key));
22352 if (it != end())
22353 {
22354 return it->template get<ReturnType>();
22355 }
22356 
22357 return std::forward<ValueType>(default_value);
22358 }
22359 
22360 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22361 }
22362 
22363 /// @brief access specified object element via JSON Pointer with default value
22364 /// @sa https://json.nlohmann.me/api/basic_json/value/
22365 template < class ValueType, detail::enable_if_t <
22366 detail::is_getable<basic_json_t, ValueType>::value
22367 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22368 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22369 {
22370 // value only works for objects
22371 if (JSON_HEDLEY_LIKELY(is_object()))
22372 {
22373 // if pointer resolves a value, return it or use default value
22374 JSON_TRY
22375 {
22376 return ptr.get_checked(this).template get<ValueType>();
22377 }
22378 JSON_INTERNAL_CATCH (out_of_range&)
22379 {
22380 return default_value;
22381 }
22382 }
22383 
22384 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22385 }
22386 
22387 /// @brief access specified object element via JSON Pointer with default value
22388 /// @sa https://json.nlohmann.me/api/basic_json/value/
22389 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22390 detail::enable_if_t <
22391 detail::is_getable<basic_json_t, ReturnType>::value
22392 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22393 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22394 {
22395 // value only works for objects
22396 if (JSON_HEDLEY_LIKELY(is_object()))
22397 {
22398 // if pointer resolves a value, return it or use default value
22399 JSON_TRY
22400 {
22401 return ptr.get_checked(this).template get<ReturnType>();
22402 }
22403 JSON_INTERNAL_CATCH (out_of_range&)
22404 {
22405 return std::forward<ValueType>(default_value);
22406 }
22407 }
22408 
22409 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22410 }
22411 
22412 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22413 detail::is_basic_json<BasicJsonType>::value
22414 && detail::is_getable<basic_json_t, ValueType>::value
22415 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22416 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22417 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22418 {
22419 return value(ptr.convert(), default_value);
22420 }
22421 
22422 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22423 detail::enable_if_t <
22424 detail::is_basic_json<BasicJsonType>::value
22425 && detail::is_getable<basic_json_t, ReturnType>::value
22426 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22427 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22428 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22429 {
22430 return value(ptr.convert(), std::forward<ValueType>(default_value));
22431 }
22432 
22433 /// @brief access the first element
22434 /// @sa https://json.nlohmann.me/api/basic_json/front/
22435 reference front()
22436 {
22437 return *begin();
22438 }
22439 
22440 /// @brief access the first element
22441 /// @sa https://json.nlohmann.me/api/basic_json/front/
22442 const_reference front() const
22443 {
22444 return *cbegin();
22445 }
22446 
22447 /// @brief access the last element
22448 /// @sa https://json.nlohmann.me/api/basic_json/back/
22449 reference back()
22450 {
22451 auto tmp = end();
22452 --tmp;
22453 return *tmp;
22454 }
22455 
22456 /// @brief access the last element
22457 /// @sa https://json.nlohmann.me/api/basic_json/back/
22458 const_reference back() const
22459 {
22460 auto tmp = cend();
22461 --tmp;
22462 return *tmp;
22463 }
22464 
22465 /// @brief remove element given an iterator
22466 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22467 template < class IteratorType, detail::enable_if_t <
22468 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22469 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22470 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22471 {
22472 // make sure iterator fits the current value
22473 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22474 {
22475 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22476 }
22477 
22478 IteratorType result = end();
22479 
22480 switch (m_data.m_type)
22481 {
22482 case value_t::boolean:
22483 case value_t::number_float:
22484 case value_t::number_integer:
22485 case value_t::number_unsigned:
22486 case value_t::string:
22487 case value_t::binary:
22488 {
22489 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22490 {
22491 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22492 }
22493 
22494 if (is_string())
22495 {
22496 AllocatorType<string_t> alloc;
22497 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22498 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22499 m_data.m_value.string = nullptr;
22500 }
22501 else if (is_binary())
22502 {
22503 AllocatorType<binary_t> alloc;
22504 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22505 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22506 m_data.m_value.binary = nullptr;
22507 }
22508 
22509 m_data.m_type = value_t::null;
22510 assert_invariant();
22511 break;
22512 }
22513 
22514 case value_t::object:
22515 {
22516 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22517 break;
22518 }
22519 
22520 case value_t::array:
22521 {
22522 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22523 break;
22524 }
22525 
22526 case value_t::null:
22527 case value_t::discarded:
22528 default:
22529 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22530 }
22531 
22532 return result;
22533 }
22534 
22535 /// @brief remove elements given an iterator range
22536 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22537 template < class IteratorType, detail::enable_if_t <
22538 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22539 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22540 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22541 {
22542 // make sure iterator fits the current value
22543 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22544 {
22545 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22546 }
22547 
22548 IteratorType result = end();
22549 
22550 switch (m_data.m_type)
22551 {
22552 case value_t::boolean:
22553 case value_t::number_float:
22554 case value_t::number_integer:
22555 case value_t::number_unsigned:
22556 case value_t::string:
22557 case value_t::binary:
22558 {
22559 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22560 || !last.m_it.primitive_iterator.is_end()))
22561 {
22562 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22563 }
22564 
22565 if (is_string())
22566 {
22567 AllocatorType<string_t> alloc;
22568 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22569 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22570 m_data.m_value.string = nullptr;
22571 }
22572 else if (is_binary())
22573 {
22574 AllocatorType<binary_t> alloc;
22575 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22576 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22577 m_data.m_value.binary = nullptr;
22578 }
22579 
22580 m_data.m_type = value_t::null;
22581 assert_invariant();
22582 break;
22583 }
22584 
22585 case value_t::object:
22586 {
22587 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22588 last.m_it.object_iterator);
22589 break;
22590 }
22591 
22592 case value_t::array:
22593 {
22594 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22595 last.m_it.array_iterator);
22596 break;
22597 }
22598 
22599 case value_t::null:
22600 case value_t::discarded:
22601 default:
22602 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22603 }
22604 
22605 return result;
22606 }
22607 
22608 private:
22609 template < typename KeyType, detail::enable_if_t <
22610 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22611 size_type erase_internal(KeyType && key)
22612 {
22613 // this erase only works for objects
22614 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22615 {
22616 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22617 }
22618 
22619 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22620 }
22621 
22622 template < typename KeyType, detail::enable_if_t <
22623 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22624 size_type erase_internal(KeyType && key)
22625 {
22626 // this erase only works for objects
22627 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22628 {
22629 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22630 }
22631 
22632 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22633 if (it != m_data.m_value.object->end())
22634 {
22635 m_data.m_value.object->erase(it);
22636 return 1;
22637 }
22638 return 0;
22639 }
22640 
22641 public:
22642 
22643 /// @brief remove element from a JSON object given a key
22644 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22645 size_type erase(const typename object_t::key_type& key)
22646 {
22647 // the indirection via erase_internal() is added to avoid making this
22648 // function a template and thus de-rank it during overload resolution
22649 return erase_internal(key);
22650 }
22651 
22652 /// @brief remove element from a JSON object given a key
22653 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22654 template<class KeyType, detail::enable_if_t<
22655 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22656 size_type erase(KeyType && key)
22657 {
22658 return erase_internal(std::forward<KeyType>(key));
22659 }
22660 
22661 /// @brief remove element from a JSON array given an index
22662 /// @sa https://json.nlohmann.me/api/basic_json/erase/
22663 void erase(const size_type idx)
22664 {
22665 // this erase only works for arrays
22666 if (JSON_HEDLEY_LIKELY(is_array()))
22667 {
22668 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22669 {
22670 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22671 }
22672 
22673 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22674 }
22675 else
22676 {
22677 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22678 }
22679 }
22680 
22681 /// @}
22682 
22683 ////////////
22684 // lookup //
22685 ////////////
22686 
22687 /// @name lookup
22688 /// @{
22689 
22690 /// @brief find an element in a JSON object
22691 /// @sa https://json.nlohmann.me/api/basic_json/find/
22692 iterator find(const typename object_t::key_type& key)
22693 {
22694 auto result = end();
22695 
22696 if (is_object())
22697 {
22698 result.m_it.object_iterator = m_data.m_value.object->find(key);
22699 }
22700 
22701 return result;
22702 }
22703 
22704 /// @brief find an element in a JSON object
22705 /// @sa https://json.nlohmann.me/api/basic_json/find/
22706 const_iterator find(const typename object_t::key_type& key) const
22707 {
22708 auto result = cend();
22709 
22710 if (is_object())
22711 {
22712 result.m_it.object_iterator = m_data.m_value.object->find(key);
22713 }
22714 
22715 return result;
22716 }
22717 
22718 /// @brief find an element in a JSON object
22719 /// @sa https://json.nlohmann.me/api/basic_json/find/
22720 template<class KeyType, detail::enable_if_t<
22721 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22722 iterator find(KeyType && key)
22723 {
22724 auto result = end();
22725 
22726 if (is_object())
22727 {
22728 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22729 }
22730 
22731 return result;
22732 }
22733 
22734 /// @brief find an element in a JSON object
22735 /// @sa https://json.nlohmann.me/api/basic_json/find/
22736 template<class KeyType, detail::enable_if_t<
22737 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22738 const_iterator find(KeyType && key) const
22739 {
22740 auto result = cend();
22741 
22742 if (is_object())
22743 {
22744 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22745 }
22746 
22747 return result;
22748 }
22749 
22750 /// @brief returns the number of occurrences of a key in a JSON object
22751 /// @sa https://json.nlohmann.me/api/basic_json/count/
22752 size_type count(const typename object_t::key_type& key) const
22753 {
22754 // return 0 for all nonobject types
22755 return is_object() ? m_data.m_value.object->count(key) : 0;
22756 }
22757 
22758 /// @brief returns the number of occurrences of a key in a JSON object
22759 /// @sa https://json.nlohmann.me/api/basic_json/count/
22760 template<class KeyType, detail::enable_if_t<
22761 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22762 size_type count(KeyType && key) const
22763 {
22764 // return 0 for all nonobject types
22765 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22766 }
22767 
22768 /// @brief check the existence of an element in a JSON object
22769 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22770 bool contains(const typename object_t::key_type& key) const
22771 {
22772 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22773 }
22774 
22775 /// @brief check the existence of an element in a JSON object
22776 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22777 template<class KeyType, detail::enable_if_t<
22778 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22779 bool contains(KeyType && key) const
22780 {
22781 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22782 }
22783 
22784 /// @brief check the existence of an element in a JSON object given a JSON pointer
22785 /// @sa https://json.nlohmann.me/api/basic_json/contains/
22786 bool contains(const json_pointer& ptr) const
22787 {
22788 return ptr.contains(this);
22789 }
22790 
22791 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22792 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22793 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22794 {
22795 return ptr.contains(this);
22796 }
22797 
22798 /// @}
22799 
22800 ///////////////
22801 // iterators //
22802 ///////////////
22803 
22804 /// @name iterators
22805 /// @{
22806 
22807 /// @brief returns an iterator to the first element
22808 /// @sa https://json.nlohmann.me/api/basic_json/begin/
22809 iterator begin() noexcept
22810 {
22811 iterator result(this);
22812 result.set_begin();
22813 return result;
22814 }
22815 
22816 /// @brief returns an iterator to the first element
22817 /// @sa https://json.nlohmann.me/api/basic_json/begin/
22818 const_iterator begin() const noexcept
22819 {
22820 return cbegin();
22821 }
22822 
22823 /// @brief returns a const iterator to the first element
22824 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22825 const_iterator cbegin() const noexcept
22826 {
22827 const_iterator result(this);
22828 result.set_begin();
22829 return result;
22830 }
22831 
22832 /// @brief returns an iterator to one past the last element
22833 /// @sa https://json.nlohmann.me/api/basic_json/end/
22834 iterator end() noexcept
22835 {
22836 iterator result(this);
22837 result.set_end();
22838 return result;
22839 }
22840 
22841 /// @brief returns an iterator to one past the last element
22842 /// @sa https://json.nlohmann.me/api/basic_json/end/
22843 const_iterator end() const noexcept
22844 {
22845 return cend();
22846 }
22847 
22848 /// @brief returns an iterator to one past the last element
22849 /// @sa https://json.nlohmann.me/api/basic_json/cend/
22850 const_iterator cend() const noexcept
22851 {
22852 const_iterator result(this);
22853 result.set_end();
22854 return result;
22855 }
22856 
22857 /// @brief returns an iterator to the reverse-beginning
22858 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22859 reverse_iterator rbegin() noexcept
22860 {
22861 return reverse_iterator(end());
22862 }
22863 
22864 /// @brief returns an iterator to the reverse-beginning
22865 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22866 const_reverse_iterator rbegin() const noexcept
22867 {
22868 return crbegin();
22869 }
22870 
22871 /// @brief returns an iterator to the reverse-end
22872 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22873 reverse_iterator rend() noexcept
22874 {
22875 return reverse_iterator(begin());
22876 }
22877 
22878 /// @brief returns an iterator to the reverse-end
22879 /// @sa https://json.nlohmann.me/api/basic_json/rend/
22880 const_reverse_iterator rend() const noexcept
22881 {
22882 return crend();
22883 }
22884 
22885 /// @brief returns a const reverse iterator to the last element
22886 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22887 const_reverse_iterator crbegin() const noexcept
22888 {
22889 return const_reverse_iterator(cend());
22890 }
22891 
22892 /// @brief returns a const reverse iterator to one before the first
22893 /// @sa https://json.nlohmann.me/api/basic_json/crend/
22894 const_reverse_iterator crend() const noexcept
22895 {
22896 return const_reverse_iterator(cbegin());
22897 }
22898 
22899 public:
22900 /// @brief wrapper to access iterator member functions in range-based for
22901 /// @sa https://json.nlohmann.me/api/basic_json/items/
22902 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22903 /// version 4.0.0 of the library. Please use @ref items() instead;
22904 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22905 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22906 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22907 {
22908 return ref.items();
22909 }
22910 
22911 /// @brief wrapper to access iterator member functions in range-based for
22912 /// @sa https://json.nlohmann.me/api/basic_json/items/
22913 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22914 /// version 4.0.0 of the library. Please use @ref items() instead;
22915 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22916 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22917 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22918 {
22919 return ref.items();
22920 }
22921 
22922 /// @brief helper to access iterator member functions in range-based for
22923 /// @sa https://json.nlohmann.me/api/basic_json/items/
22924 iteration_proxy<iterator> items() noexcept
22925 {
22926 return iteration_proxy<iterator>(*this);
22927 }
22928 
22929 /// @brief helper to access iterator member functions in range-based for
22930 /// @sa https://json.nlohmann.me/api/basic_json/items/
22931 iteration_proxy<const_iterator> items() const noexcept
22932 {
22933 return iteration_proxy<const_iterator>(*this);
22934 }
22935 
22936 /// @}
22937 
22938 //////////////
22939 // capacity //
22940 //////////////
22941 
22942 /// @name capacity
22943 /// @{
22944 
22945 /// @brief checks whether the container is empty.
22946 /// @sa https://json.nlohmann.me/api/basic_json/empty/
22947 bool empty() const noexcept
22948 {
22949 switch (m_data.m_type)
22950 {
22951 case value_t::null:
22952 {
22953 // null values are empty
22954 return true;
22955 }
22956 
22957 case value_t::array:
22958 {
22959 // delegate call to array_t::empty()
22960 return m_data.m_value.array->empty();
22961 }
22962 
22963 case value_t::object:
22964 {
22965 // delegate call to object_t::empty()
22966 return m_data.m_value.object->empty();
22967 }
22968 
22969 case value_t::string:
22970 case value_t::boolean:
22971 case value_t::number_integer:
22972 case value_t::number_unsigned:
22973 case value_t::number_float:
22974 case value_t::binary:
22975 case value_t::discarded:
22976 default:
22977 {
22978 // all other types are nonempty
22979 return false;
22980 }
22981 }
22982 }
22983 
22984 /// @brief returns the number of elements
22985 /// @sa https://json.nlohmann.me/api/basic_json/size/
22986 size_type size() const noexcept
22987 {
22988 switch (m_data.m_type)
22989 {
22990 case value_t::null:
22991 {
22992 // null values are empty
22993 return 0;
22994 }
22995 
22996 case value_t::array:
22997 {
22998 // delegate call to array_t::size()
22999 return m_data.m_value.array->size();
23000 }
23001 
23002 case value_t::object:
23003 {
23004 // delegate call to object_t::size()
23005 return m_data.m_value.object->size();
23006 }
23007 
23008 case value_t::string:
23009 case value_t::boolean:
23010 case value_t::number_integer:
23011 case value_t::number_unsigned:
23012 case value_t::number_float:
23013 case value_t::binary:
23014 case value_t::discarded:
23015 default:
23016 {
23017 // all other types have size 1
23018 return 1;
23019 }
23020 }
23021 }
23022 
23023 /// @brief returns the maximum possible number of elements
23024 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
23025 size_type max_size() const noexcept
23026 {
23027 switch (m_data.m_type)
23028 {
23029 case value_t::array:
23030 {
23031 // delegate call to array_t::max_size()
23032 return m_data.m_value.array->max_size();
23033 }
23034 
23035 case value_t::object:
23036 {
23037 // delegate call to object_t::max_size()
23038 return m_data.m_value.object->max_size();
23039 }
23040 
23041 case value_t::null:
23042 case value_t::string:
23043 case value_t::boolean:
23044 case value_t::number_integer:
23045 case value_t::number_unsigned:
23046 case value_t::number_float:
23047 case value_t::binary:
23048 case value_t::discarded:
23049 default:
23050 {
23051 // all other types have max_size() == size()
23052 return size();
23053 }
23054 }
23055 }
23056 
23057 /// @}
23058 
23059 ///////////////
23060 // modifiers //
23061 ///////////////
23062 
23063 /// @name modifiers
23064 /// @{
23065 
23066 /// @brief clears the contents
23067 /// @sa https://json.nlohmann.me/api/basic_json/clear/
23068 void clear() noexcept
23069 {
23070 switch (m_data.m_type)
23071 {
23072 case value_t::number_integer:
23073 {
23074 m_data.m_value.number_integer = 0;
23075 break;
23076 }
23077 
23078 case value_t::number_unsigned:
23079 {
23080 m_data.m_value.number_unsigned = 0;
23081 break;
23082 }
23083 
23084 case value_t::number_float:
23085 {
23086 m_data.m_value.number_float = 0.0;
23087 break;
23088 }
23089 
23090 case value_t::boolean:
23091 {
23092 m_data.m_value.boolean = false;
23093 break;
23094 }
23095 
23096 case value_t::string:
23097 {
23098 m_data.m_value.string->clear();
23099 break;
23100 }
23101 
23102 case value_t::binary:
23103 {
23104 m_data.m_value.binary->clear();
23105 break;
23106 }
23107 
23108 case value_t::array:
23109 {
23110 m_data.m_value.array->clear();
23111 break;
23112 }
23113 
23114 case value_t::object:
23115 {
23116 m_data.m_value.object->clear();
23117 break;
23118 }
23119 
23120 case value_t::null:
23121 case value_t::discarded:
23122 default:
23123 break;
23124 }
23125 }
23126 
23127 /// @brief add an object to an array
23128 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23129 void push_back(basic_json&& val)
23130 {
23131 // push_back only works for null objects or arrays
23132 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23133 {
23134 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23135 }
23136 
23137 // transform null object into an array
23138 if (is_null())
23139 {
23140 m_data.m_type = value_t::array;
23141 m_data.m_value = value_t::array;
23142 assert_invariant();
23143 }
23144 
23145 // add element to array (move semantics)
23146 const auto old_capacity = m_data.m_value.array->capacity();
23147 m_data.m_value.array->push_back(std::move(val));
23148 set_parent(m_data.m_value.array->back(), old_capacity);
23149 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23150 }
23151 
23152 /// @brief add an object to an array
23153 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23154 reference operator+=(basic_json&& val)
23155 {
23156 push_back(std::move(val));
23157 return *this;
23158 }
23159 
23160 /// @brief add an object to an array
23161 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23162 void push_back(const basic_json& val)
23163 {
23164 // push_back only works for null objects or arrays
23165 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23166 {
23167 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23168 }
23169 
23170 // transform null object into an array
23171 if (is_null())
23172 {
23173 m_data.m_type = value_t::array;
23174 m_data.m_value = value_t::array;
23175 assert_invariant();
23176 }
23177 
23178 // add element to array
23179 const auto old_capacity = m_data.m_value.array->capacity();
23180 m_data.m_value.array->push_back(val);
23181 set_parent(m_data.m_value.array->back(), old_capacity);
23182 }
23183 
23184 /// @brief add an object to an array
23185 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23186 reference operator+=(const basic_json& val)
23187 {
23188 push_back(val);
23189 return *this;
23190 }
23191 
23192 /// @brief add an object to an object
23193 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23194 void push_back(const typename object_t::value_type& val)
23195 {
23196 // push_back only works for null objects or objects
23197 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23198 {
23199 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23200 }
23201 
23202 // transform null object into an object
23203 if (is_null())
23204 {
23205 m_data.m_type = value_t::object;
23206 m_data.m_value = value_t::object;
23207 assert_invariant();
23208 }
23209 
23210 // add element to object
23211 auto res = m_data.m_value.object->insert(val);
23212 set_parent(res.first->second);
23213 }
23214 
23215 /// @brief add an object to an object
23216 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23217 reference operator+=(const typename object_t::value_type& val)
23218 {
23219 push_back(val);
23220 return *this;
23221 }
23222 
23223 /// @brief add an object to an object
23224 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23225 void push_back(initializer_list_t init)
23226 {
23227 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23228 {
23229 basic_json&& key = init.begin()->moved_or_copied();
23230 push_back(typename object_t::value_type(
23231 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23232 }
23233 else
23234 {
23235 push_back(basic_json(init));
23236 }
23237 }
23238 
23239 /// @brief add an object to an object
23240 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23241 reference operator+=(initializer_list_t init)
23242 {
23243 push_back(init);
23244 return *this;
23245 }
23246 
23247 /// @brief add an object to an array
23248 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
23249 template<class... Args>
23250 reference emplace_back(Args&& ... args)
23251 {
23252 // emplace_back only works for null objects or arrays
23253 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23254 {
23255 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23256 }
23257 
23258 // transform null object into an array
23259 if (is_null())
23260 {
23261 m_data.m_type = value_t::array;
23262 m_data.m_value = value_t::array;
23263 assert_invariant();
23264 }
23265 
23266 // add element to array (perfect forwarding)
23267 const auto old_capacity = m_data.m_value.array->capacity();
23268 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23269 return set_parent(m_data.m_value.array->back(), old_capacity);
23270 }
23271 
23272 /// @brief add an object to an object if key does not exist
23273 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
23274 template<class... Args>
23275 std::pair<iterator, bool> emplace(Args&& ... args)
23276 {
23277 // emplace only works for null objects or arrays
23278 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23279 {
23280 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23281 }
23282 
23283 // transform null object into an object
23284 if (is_null())
23285 {
23286 m_data.m_type = value_t::object;
23287 m_data.m_value = value_t::object;
23288 assert_invariant();
23289 }
23290 
23291 // add element to array (perfect forwarding)
23292 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23293 set_parent(res.first->second);
23294 
23295 // create result iterator and set iterator to the result of emplace
23296 auto it = begin();
23297 it.m_it.object_iterator = res.first;
23298 
23299 // return pair of iterator and boolean
23300 return {it, res.second};
23301 }
23302 
23303 /// Helper for insertion of an iterator
23304 /// @note: This uses std::distance to support GCC 4.8,
23305 /// see https://github.com/nlohmann/json/pull/1257
23306 template<typename... Args>
23307 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23308 {
23309 iterator result(this);
23310 JSON_ASSERT(m_data.m_value.array != nullptr);
23311 
23312 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23313 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23314 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23315 
23316 // This could have been written as:
23317 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23318 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23319 
23320 set_parents();
23321 return result;
23322 }
23323 
23324 /// @brief inserts element into array
23325 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23326 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23327 {
23328 // insert only works for arrays
23329 if (JSON_HEDLEY_LIKELY(is_array()))
23330 {
23331 // check if iterator pos fits to this JSON value
23332 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23333 {
23334 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23335 }
23336 
23337 // insert to array and return iterator
23338 return insert_iterator(pos, val);
23339 }
23340 
23341 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23342 }
23343 
23344 /// @brief inserts element into array
23345 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23346 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23347 {
23348 return insert(pos, val);
23349 }
23350 
23351 /// @brief inserts copies of element into array
23352 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23353 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23354 {
23355 // insert only works for arrays
23356 if (JSON_HEDLEY_LIKELY(is_array()))
23357 {
23358 // check if iterator pos fits to this JSON value
23359 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23360 {
23361 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23362 }
23363 
23364 // insert to array and return iterator
23365 return insert_iterator(pos, cnt, val);
23366 }
23367 
23368 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23369 }
23370 
23371 /// @brief inserts range of elements into array
23372 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23373 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23374 {
23375 // insert only works for arrays
23376 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23377 {
23378 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23379 }
23380 
23381 // check if iterator pos fits to this JSON value
23382 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23383 {
23384 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23385 }
23386 
23387 // check if range iterators belong to the same JSON object
23388 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23389 {
23390 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23391 }
23392 
23393 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23394 {
23395 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23396 }
23397 
23398 // insert to array and return iterator
23399 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23400 }
23401 
23402 /// @brief inserts elements from initializer list into array
23403 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23404 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23405 {
23406 // insert only works for arrays
23407 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23408 {
23409 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23410 }
23411 
23412 // check if iterator pos fits to this JSON value
23413 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23414 {
23415 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23416 }
23417 
23418 // insert to array and return iterator
23419 return insert_iterator(pos, ilist.begin(), ilist.end());
23420 }
23421 
23422 /// @brief inserts range of elements into object
23423 /// @sa https://json.nlohmann.me/api/basic_json/insert/
23424 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23425 {
23426 // insert only works for objects
23427 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23428 {
23429 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23430 }
23431 
23432 // check if range iterators belong to the same JSON object
23433 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23434 {
23435 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23436 }
23437 
23438 // passed iterators must belong to objects
23439 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23440 {
23441 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23442 }
23443 
23444 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23445 set_parents();
23446 }
23447 
23448 /// @brief updates a JSON object from another object, overwriting existing keys
23449 /// @sa https://json.nlohmann.me/api/basic_json/update/
23450 void update(const_reference j, bool merge_objects = false)
23451 {
23452 update(j.begin(), j.end(), merge_objects);
23453 }
23454 
23455 /// @brief updates a JSON object from another object, overwriting existing keys
23456 /// @sa https://json.nlohmann.me/api/basic_json/update/
23457 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23458 {
23459 // implicitly convert null value to an empty object
23460 if (is_null())
23461 {
23462 m_data.m_type = value_t::object;
23463 m_data.m_value.object = create<object_t>();
23464 assert_invariant();
23465 }
23466 
23467 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23468 {
23469 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23470 }
23471 
23472 // check if range iterators belong to the same JSON object
23473 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23474 {
23475 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23476 }
23477 
23478 // passed iterators must belong to objects
23479 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23480 {
23481 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23482 }
23483 
23484 for (auto it = first; it != last; ++it)
23485 {
23486 if (merge_objects && it.value().is_object())
23487 {
23488 auto it2 = m_data.m_value.object->find(it.key());
23489 if (it2 != m_data.m_value.object->end())
23490 {
23491 it2->second.update(it.value(), true);
23492 continue;
23493 }
23494 }
23495 m_data.m_value.object->operator[](it.key()) = it.value();
23496#if JSON_DIAGNOSTICS
23497 m_data.m_value.object->operator[](it.key()).m_parent = this;
23498#endif
23499 }
23500 }
23501 
23502 /// @brief exchanges the values
23503 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23504 void swap(reference other) noexcept (
23505 std::is_nothrow_move_constructible<value_t>::value&&
23506 std::is_nothrow_move_assignable<value_t>::value&&
23507 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23508 std::is_nothrow_move_assignable<json_value>::value
23509 )
23510 {
23511 std::swap(m_data.m_type, other.m_data.m_type);
23512 std::swap(m_data.m_value, other.m_data.m_value);
23513 
23514 set_parents();
23515 other.set_parents();
23516 assert_invariant();
23517 }
23518 
23519 /// @brief exchanges the values
23520 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23521 friend void swap(reference left, reference right) noexcept (
23522 std::is_nothrow_move_constructible<value_t>::value&&
23523 std::is_nothrow_move_assignable<value_t>::value&&
23524 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23525 std::is_nothrow_move_assignable<json_value>::value
23526 )
23527 {
23528 left.swap(right);
23529 }
23530 
23531 /// @brief exchanges the values
23532 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23533 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23534 {
23535 // swap only works for arrays
23536 if (JSON_HEDLEY_LIKELY(is_array()))
23537 {
23538 using std::swap;
23539 swap(*(m_data.m_value.array), other);
23540 }
23541 else
23542 {
23543 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23544 }
23545 }
23546 
23547 /// @brief exchanges the values
23548 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23549 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23550 {
23551 // swap only works for objects
23552 if (JSON_HEDLEY_LIKELY(is_object()))
23553 {
23554 using std::swap;
23555 swap(*(m_data.m_value.object), other);
23556 }
23557 else
23558 {
23559 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23560 }
23561 }
23562 
23563 /// @brief exchanges the values
23564 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23565 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23566 {
23567 // swap only works for strings
23568 if (JSON_HEDLEY_LIKELY(is_string()))
23569 {
23570 using std::swap;
23571 swap(*(m_data.m_value.string), other);
23572 }
23573 else
23574 {
23575 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23576 }
23577 }
23578 
23579 /// @brief exchanges the values
23580 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23581 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23582 {
23583 // swap only works for strings
23584 if (JSON_HEDLEY_LIKELY(is_binary()))
23585 {
23586 using std::swap;
23587 swap(*(m_data.m_value.binary), other);
23588 }
23589 else
23590 {
23591 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23592 }
23593 }
23594 
23595 /// @brief exchanges the values
23596 /// @sa https://json.nlohmann.me/api/basic_json/swap/
23597 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23598 {
23599 // swap only works for strings
23600 if (JSON_HEDLEY_LIKELY(is_binary()))
23601 {
23602 using std::swap;
23603 swap(*(m_data.m_value.binary), other);
23604 }
23605 else
23606 {
23607 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23608 }
23609 }
23610 
23611 /// @}
23612 
23613 //////////////////////////////////////////
23614 // lexicographical comparison operators //
23615 //////////////////////////////////////////
23616 
23617 /// @name lexicographical comparison operators
23618 /// @{
23619 
23620 // note parentheses around operands are necessary; see
23621 // https://github.com/nlohmann/json/issues/1530
23622#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23623 const auto lhs_type = lhs.type(); \
23624 const auto rhs_type = rhs.type(); \
23625 \
23626 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23627 { \
23628 switch (lhs_type) \
23629 { \
23630 case value_t::array: \
23631 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23632 \
23633 case value_t::object: \
23634 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23635 \
23636 case value_t::null: \
23637 return (null_result); \
23638 \
23639 case value_t::string: \
23640 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23641 \
23642 case value_t::boolean: \
23643 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23644 \
23645 case value_t::number_integer: \
23646 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23647 \
23648 case value_t::number_unsigned: \
23649 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23650 \
23651 case value_t::number_float: \
23652 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23653 \
23654 case value_t::binary: \
23655 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23656 \
23657 case value_t::discarded: \
23658 default: \
23659 return (unordered_result); \
23660 } \
23661 } \
23662 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23663 { \
23664 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23665 } \
23666 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23667 { \
23668 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23669 } \
23670 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23671 { \
23672 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23673 } \
23674 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23675 { \
23676 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23677 } \
23678 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23679 { \
23680 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23681 } \
23682 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23683 { \
23684 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23685 } \
23686 else if(compares_unordered(lhs, rhs))\
23687 {\
23688 return (unordered_result);\
23689 }\
23690 \
23691 return (default_result);
23692 
23693 JSON_PRIVATE_UNLESS_TESTED:
23694 // returns true if:
23695 // - any operand is NaN and the other operand is of number type
23696 // - any operand is discarded
23697 // in legacy mode, discarded values are considered ordered if
23698 // an operation is computed as an odd number of inverses of others
23699 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23700 {
23701 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23702 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23703 {
23704 return true;
23705 }
23706#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23707 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23708#else
23709 static_cast<void>(inverse);
23710 return lhs.is_discarded() || rhs.is_discarded();
23711#endif
23712 }
23713 
23714 private:
23715 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23716 {
23717 return compares_unordered(*this, rhs, inverse);
23718 }
23719 
23720 public:
23721#if JSON_HAS_THREE_WAY_COMPARISON
23722 /// @brief comparison: equal
23723 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23724 bool operator==(const_reference rhs) const noexcept
23725 {
23726#ifdef __GNUC__
23727#pragma GCC diagnostic push
23728#pragma GCC diagnostic ignored "-Wfloat-equal"
23729#endif
23730 const_reference lhs = *this;
23731 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23732#ifdef __GNUC__
23733#pragma GCC diagnostic pop
23734#endif
23735 }
23736 
23737 /// @brief comparison: equal
23738 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23739 template<typename ScalarType>
23740 requires std::is_scalar_v<ScalarType>
23741 bool operator==(ScalarType rhs) const noexcept
23742 {
23743 return *this == basic_json(rhs);
23744 }
23745 
23746 /// @brief comparison: not equal
23747 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23748 bool operator!=(const_reference rhs) const noexcept
23749 {
23750 if (compares_unordered(rhs, true))
23751 {
23752 return false;
23753 }
23754 return !operator==(rhs);
23755 }
23756 
23757 /// @brief comparison: 3-way
23758 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23759 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23760 {
23761 const_reference lhs = *this;
23762 // default_result is used if we cannot compare values. In that case,
23763 // we compare types.
23764 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23765 std::partial_ordering::equivalent,
23766 std::partial_ordering::unordered,
23767 lhs_type <=> rhs_type) // *NOPAD*
23768 }
23769 
23770 /// @brief comparison: 3-way
23771 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23772 template<typename ScalarType>
23773 requires std::is_scalar_v<ScalarType>
23774 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23775 {
23776 return *this <=> basic_json(rhs); // *NOPAD*
23777 }
23778 
23779#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23780 // all operators that are computed as an odd number of inverses of others
23781 // need to be overloaded to emulate the legacy comparison behavior
23782 
23783 /// @brief comparison: less than or equal
23784 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23785 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23786 bool operator<=(const_reference rhs) const noexcept
23787 {
23788 if (compares_unordered(rhs, true))
23789 {
23790 return false;
23791 }
23792 return !(rhs < *this);
23793 }
23794 
23795 /// @brief comparison: less than or equal
23796 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23797 template<typename ScalarType>
23798 requires std::is_scalar_v<ScalarType>
23799 bool operator<=(ScalarType rhs) const noexcept
23800 {
23801 return *this <= basic_json(rhs);
23802 }
23803 
23804 /// @brief comparison: greater than or equal
23805 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23806 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23807 bool operator>=(const_reference rhs) const noexcept
23808 {
23809 if (compares_unordered(rhs, true))
23810 {
23811 return false;
23812 }
23813 return !(*this < rhs);
23814 }
23815 
23816 /// @brief comparison: greater than or equal
23817 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23818 template<typename ScalarType>
23819 requires std::is_scalar_v<ScalarType>
23820 bool operator>=(ScalarType rhs) const noexcept
23821 {
23822 return *this >= basic_json(rhs);
23823 }
23824#endif
23825#else
23826 /// @brief comparison: equal
23827 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23828 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23829 {
23830#ifdef __GNUC__
23831#pragma GCC diagnostic push
23832#pragma GCC diagnostic ignored "-Wfloat-equal"
23833#endif
23834 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23835#ifdef __GNUC__
23836#pragma GCC diagnostic pop
23837#endif
23838 }
23839 
23840 /// @brief comparison: equal
23841 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23842 template<typename ScalarType, typename std::enable_if<
23843 std::is_scalar<ScalarType>::value, int>::type = 0>
23844 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23845 {
23846 return lhs == basic_json(rhs);
23847 }
23848 
23849 /// @brief comparison: equal
23850 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23851 template<typename ScalarType, typename std::enable_if<
23852 std::is_scalar<ScalarType>::value, int>::type = 0>
23853 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23854 {
23855 return basic_json(lhs) == rhs;
23856 }
23857 
23858 /// @brief comparison: not equal
23859 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23860 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23861 {
23862 if (compares_unordered(lhs, rhs, true))
23863 {
23864 return false;
23865 }
23866 return !(lhs == rhs);
23867 }
23868 
23869 /// @brief comparison: not equal
23870 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23871 template<typename ScalarType, typename std::enable_if<
23872 std::is_scalar<ScalarType>::value, int>::type = 0>
23873 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23874 {
23875 return lhs != basic_json(rhs);
23876 }
23877 
23878 /// @brief comparison: not equal
23879 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23880 template<typename ScalarType, typename std::enable_if<
23881 std::is_scalar<ScalarType>::value, int>::type = 0>
23882 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23883 {
23884 return basic_json(lhs) != rhs;
23885 }
23886 
23887 /// @brief comparison: less than
23888 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23889 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23890 {
23891 // default_result is used if we cannot compare values. In that case,
23892 // we compare types. Note we have to call the operator explicitly,
23893 // because MSVC has problems otherwise.
23894 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23895 }
23896 
23897 /// @brief comparison: less than
23898 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23899 template<typename ScalarType, typename std::enable_if<
23900 std::is_scalar<ScalarType>::value, int>::type = 0>
23901 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23902 {
23903 return lhs < basic_json(rhs);
23904 }
23905 
23906 /// @brief comparison: less than
23907 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23908 template<typename ScalarType, typename std::enable_if<
23909 std::is_scalar<ScalarType>::value, int>::type = 0>
23910 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23911 {
23912 return basic_json(lhs) < rhs;
23913 }
23914 
23915 /// @brief comparison: less than or equal
23916 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23917 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23918 {
23919 if (compares_unordered(lhs, rhs, true))
23920 {
23921 return false;
23922 }
23923 return !(rhs < lhs);
23924 }
23925 
23926 /// @brief comparison: less than or equal
23927 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23928 template<typename ScalarType, typename std::enable_if<
23929 std::is_scalar<ScalarType>::value, int>::type = 0>
23930 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23931 {
23932 return lhs <= basic_json(rhs);
23933 }
23934 
23935 /// @brief comparison: less than or equal
23936 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23937 template<typename ScalarType, typename std::enable_if<
23938 std::is_scalar<ScalarType>::value, int>::type = 0>
23939 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23940 {
23941 return basic_json(lhs) <= rhs;
23942 }
23943 
23944 /// @brief comparison: greater than
23945 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23946 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23947 {
23948 // double inverse
23949 if (compares_unordered(lhs, rhs))
23950 {
23951 return false;
23952 }
23953 return !(lhs <= rhs);
23954 }
23955 
23956 /// @brief comparison: greater than
23957 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23958 template<typename ScalarType, typename std::enable_if<
23959 std::is_scalar<ScalarType>::value, int>::type = 0>
23960 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23961 {
23962 return lhs > basic_json(rhs);
23963 }
23964 
23965 /// @brief comparison: greater than
23966 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23967 template<typename ScalarType, typename std::enable_if<
23968 std::is_scalar<ScalarType>::value, int>::type = 0>
23969 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23970 {
23971 return basic_json(lhs) > rhs;
23972 }
23973 
23974 /// @brief comparison: greater than or equal
23975 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23976 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23977 {
23978 if (compares_unordered(lhs, rhs, true))
23979 {
23980 return false;
23981 }
23982 return !(lhs < rhs);
23983 }
23984 
23985 /// @brief comparison: greater than or equal
23986 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23987 template<typename ScalarType, typename std::enable_if<
23988 std::is_scalar<ScalarType>::value, int>::type = 0>
23989 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23990 {
23991 return lhs >= basic_json(rhs);
23992 }
23993 
23994 /// @brief comparison: greater than or equal
23995 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23996 template<typename ScalarType, typename std::enable_if<
23997 std::is_scalar<ScalarType>::value, int>::type = 0>
23998 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23999 {
24000 return basic_json(lhs) >= rhs;
24001 }
24002#endif
24003 
24004#undef JSON_IMPLEMENT_OPERATOR
24005 
24006 /// @}
24007 
24008 ///////////////////
24009 // serialization //
24010 ///////////////////
24011 
24012 /// @name serialization
24013 /// @{
24014#ifndef JSON_NO_IO
24015 /// @brief serialize to stream
24016 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24017 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24018 {
24019 // read width member and use it as indentation parameter if nonzero
24020 const bool pretty_print = o.width() > 0;
24021 const auto indentation = pretty_print ? o.width() : 0;
24022 
24023 // reset width to 0 for subsequent calls to this stream
24024 o.width(0);
24025 
24026 // do the actual serialization
24027 serializer s(detail::output_adapter<char>(o), o.fill());
24028 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24029 return o;
24030 }
24031 
24032 /// @brief serialize to stream
24033 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24034 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
24035 /// version 4.0.0 of the library. Please use
24036 /// operator<<(std::ostream&, const basic_json&) instead; that is,
24037 /// replace calls like `j >> o;` with `o << j;`.
24038 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24039 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24040 {
24041 return o << j;
24042 }
24043#endif // JSON_NO_IO
24044 /// @}
24045 
24046 /////////////////////
24047 // deserialization //
24048 /////////////////////
24049 
24050 /// @name deserialization
24051 /// @{
24052 
24053 /// @brief deserialize from a compatible input
24054 /// @sa https://json.nlohmann.me/api/basic_json/parse/
24055 template<typename InputType>
24056 JSON_HEDLEY_WARN_UNUSED_RESULT
24057 static basic_json parse(InputType&& i,
24058 parser_callback_t cb = nullptr,
24059 const bool allow_exceptions = true,
24060 const bool ignore_comments = false)
24061 {
24062 basic_json result;
24063 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24064 return result;
24065 }
24066 
24067 /// @brief deserialize from a pair of character iterators
24068 /// @sa https://json.nlohmann.me/api/basic_json/parse/
24069 template<typename IteratorType>
24070 JSON_HEDLEY_WARN_UNUSED_RESULT
24071 static basic_json parse(IteratorType first,
24072 IteratorType last,
24073 parser_callback_t cb = nullptr,
24074 const bool allow_exceptions = true,
24075 const bool ignore_comments = false)
24076 {
24077 basic_json result;
24078 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24079 return result;
24080 }
24081 
24082 JSON_HEDLEY_WARN_UNUSED_RESULT
24083 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24084 static basic_json parse(detail::span_input_adapter&& i,
24085 parser_callback_t cb = nullptr,
24086 const bool allow_exceptions = true,
24087 const bool ignore_comments = false)
24088 {
24089 basic_json result;
24090 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24091 return result;
24092 }
24093 
24094 /// @brief check if the input is valid JSON
24095 /// @sa https://json.nlohmann.me/api/basic_json/accept/
24096 template<typename InputType>
24097 static bool accept(InputType&& i,
24098 const bool ignore_comments = false)
24099 {
24100 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
24101 }
24102 
24103 /// @brief check if the input is valid JSON
24104 /// @sa https://json.nlohmann.me/api/basic_json/accept/
24105 template<typename IteratorType>
24106 static bool accept(IteratorType first, IteratorType last,
24107 const bool ignore_comments = false)
24108 {
24109 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
24110 }
24111 
24112 JSON_HEDLEY_WARN_UNUSED_RESULT
24113 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24114 static bool accept(detail::span_input_adapter&& i,
24115 const bool ignore_comments = false)
24116 {
24117 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
24118 }
24119 
24120 /// @brief generate SAX events
24121 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24122 template <typename InputType, typename SAX>
24123 JSON_HEDLEY_NON_NULL(2)
24124 static bool sax_parse(InputType&& i, SAX* sax,
24125 input_format_t format = input_format_t::json,
24126 const bool strict = true,
24127 const bool ignore_comments = false)
24128 {
24129 auto ia = detail::input_adapter(std::forward<InputType>(i));
24130 return format == input_format_t::json
24131 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24132 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24133 }
24134 
24135 /// @brief generate SAX events
24136 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24137 template<class IteratorType, class SAX>
24138 JSON_HEDLEY_NON_NULL(3)
24139 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24140 input_format_t format = input_format_t::json,
24141 const bool strict = true,
24142 const bool ignore_comments = false)
24143 {
24144 auto ia = detail::input_adapter(std::move(first), std::move(last));
24145 return format == input_format_t::json
24146 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24147 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24148 }
24149 
24150 /// @brief generate SAX events
24151 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24152 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
24153 /// version 4.0.0 of the library. Please use
24154 /// sax_parse(ptr, ptr + len) instead.
24155 template <typename SAX>
24156 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24157 JSON_HEDLEY_NON_NULL(2)
24158 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24159 input_format_t format = input_format_t::json,
24160 const bool strict = true,
24161 const bool ignore_comments = false)
24162 {
24163 auto ia = i.get();
24164 return format == input_format_t::json
24165 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24166 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24167 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24168 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24169 }
24170#ifndef JSON_NO_IO
24171 /// @brief deserialize from stream
24172 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24173 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
24174 /// version 4.0.0 of the library. Please use
24175 /// operator>>(std::istream&, basic_json&) instead; that is,
24176 /// replace calls like `j << i;` with `i >> j;`.
24177 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24178 friend std::istream& operator<<(basic_json& j, std::istream& i)
24179 {
24180 return operator>>(i, j);
24181 }
24182 
24183 /// @brief deserialize from stream
24184 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24185 friend std::istream& operator>>(std::istream& i, basic_json& j)
24186 {
24187 parser(detail::input_adapter(i)).parse(false, j);
24188 return i;
24189 }
24190#endif // JSON_NO_IO
24191 /// @}
24192 
24193 ///////////////////////////
24194 // convenience functions //
24195 ///////////////////////////
24196 
24197 /// @brief return the type as string
24198 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
24199 JSON_HEDLEY_RETURNS_NON_NULL
24200 const char* type_name() const noexcept
24201 {
24202 switch (m_data.m_type)
24203 {
24204 case value_t::null:
24205 return "null";
24206 case value_t::object:
24207 return "object";
24208 case value_t::array:
24209 return "array";
24210 case value_t::string:
24211 return "string";
24212 case value_t::boolean:
24213 return "boolean";
24214 case value_t::binary:
24215 return "binary";
24216 case value_t::discarded:
24217 return "discarded";
24218 case value_t::number_integer:
24219 case value_t::number_unsigned:
24220 case value_t::number_float:
24221 default:
24222 return "number";
24223 }
24224 }
24225 
24226 JSON_PRIVATE_UNLESS_TESTED:
24227 //////////////////////
24228 // member variables //
24229 //////////////////////
24230 
24231 struct data
24232 {
24233 /// the type of the current element
24234 value_t m_type = value_t::null;
24235 
24236 /// the value of the current element
24237 json_value m_value = {};
24238 
24239 data(const value_t v)
24240 : m_type(v), m_value(v)
24241 {
24242 }
24243 
24244 data(size_type cnt, const basic_json& val)
24245 : m_type(value_t::array)
24246 {
24247 m_value.array = create<array_t>(cnt, val);
24248 }
24249 
24250 data() noexcept = default;
24251 data(data&&) noexcept = default;
24252 data(const data&) noexcept = delete;
24253 data& operator=(data&&) noexcept = delete;
24254 data& operator=(const data&) noexcept = delete;
24255 
24256 ~data() noexcept
24257 {
24258 m_value.destroy(m_type);
24259 }
24260 };
24261 
24262 data m_data = {};
24263 
24264#if JSON_DIAGNOSTICS
24265 /// a pointer to a parent value (for debugging purposes)
24266 basic_json* m_parent = nullptr;
24267#endif
24268 
24269#if JSON_DIAGNOSTIC_POSITIONS
24270 /// the start position of the value
24271 std::size_t start_position = std::string::npos;
24272 /// the end position of the value
24273 std::size_t end_position = std::string::npos;
24274 public:
24275 constexpr std::size_t start_pos() const noexcept
24276 {
24277 return start_position;
24278 }
24279 
24280 constexpr std::size_t end_pos() const noexcept
24281 {
24282 return end_position;
24283 }
24284#endif
24285 
24286 //////////////////////////////////////////
24287 // binary serialization/deserialization //
24288 //////////////////////////////////////////
24289 
24290 /// @name binary serialization/deserialization support
24291 /// @{
24292 
24293 public:
24294 /// @brief create a CBOR serialization of a given JSON value
24295 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24296 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24297 {
24298 std::vector<std::uint8_t> result;
24299 to_cbor(j, result);
24300 return result;
24301 }
24302 
24303 /// @brief create a CBOR serialization of a given JSON value
24304 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24305 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24306 {
24307 binary_writer<std::uint8_t>(o).write_cbor(j);
24308 }
24309 
24310 /// @brief create a CBOR serialization of a given JSON value
24311 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24312 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
24313 {
24314 binary_writer<char>(o).write_cbor(j);
24315 }
24316 
24317 /// @brief create a MessagePack serialization of a given JSON value
24318 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24319 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24320 {
24321 std::vector<std::uint8_t> result;
24322 to_msgpack(j, result);
24323 return result;
24324 }
24325 
24326 /// @brief create a MessagePack serialization of a given JSON value
24327 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24328 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24329 {
24330 binary_writer<std::uint8_t>(o).write_msgpack(j);
24331 }
24332 
24333 /// @brief create a MessagePack serialization of a given JSON value
24334 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24335 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
24336 {
24337 binary_writer<char>(o).write_msgpack(j);
24338 }
24339 
24340 /// @brief create a UBJSON serialization of a given JSON value
24341 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24342 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24343 const bool use_size = false,
24344 const bool use_type = false)
24345 {
24346 std::vector<std::uint8_t> result;
24347 to_ubjson(j, result, use_size, use_type);
24348 return result;
24349 }
24350 
24351 /// @brief create a UBJSON serialization of a given JSON value
24352 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24353 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24354 const bool use_size = false, const bool use_type = false)
24355 {
24356 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24357 }
24358 
24359 /// @brief create a UBJSON serialization of a given JSON value
24360 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24361 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
24362 const bool use_size = false, const bool use_type = false)
24363 {
24364 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24365 }
24366 
24367 /// @brief create a BJData serialization of a given JSON value
24368 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24369 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24370 const bool use_size = false,
24371 const bool use_type = false,
24372 const bjdata_version_t version = bjdata_version_t::draft2)
24373 {
24374 std::vector<std::uint8_t> result;
24375 to_bjdata(j, result, use_size, use_type, version);
24376 return result;
24377 }
24378 
24379 /// @brief create a BJData serialization of a given JSON value
24380 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24381 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24382 const bool use_size = false, const bool use_type = false,
24383 const bjdata_version_t version = bjdata_version_t::draft2)
24384 {
24385 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24386 }
24387 
24388 /// @brief create a BJData serialization of a given JSON value
24389 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24390 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
24391 const bool use_size = false, const bool use_type = false,
24392 const bjdata_version_t version = bjdata_version_t::draft2)
24393 {
24394 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24395 }
24396 
24397 /// @brief create a BSON serialization of a given JSON value
24398 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24399 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24400 {
24401 std::vector<std::uint8_t> result;
24402 to_bson(j, result);
24403 return result;
24404 }
24405 
24406 /// @brief create a BSON serialization of a given JSON value
24407 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24408 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24409 {
24410 binary_writer<std::uint8_t>(o).write_bson(j);
24411 }
24412 
24413 /// @brief create a BSON serialization of a given JSON value
24414 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24415 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
24416 {
24417 binary_writer<char>(o).write_bson(j);
24418 }
24419 
24420 /// @brief create a JSON value from an input in CBOR format
24421 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24422 template<typename InputType>
24423 JSON_HEDLEY_WARN_UNUSED_RESULT
24424 static basic_json from_cbor(InputType&& i,
24425 const bool strict = true,
24426 const bool allow_exceptions = true,
24427 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24428 {
24429 basic_json result;
24430 auto ia = detail::input_adapter(std::forward<InputType>(i));
24431 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24432 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24433 return res ? result : basic_json(value_t::discarded);
24434 }
24435 
24436 /// @brief create a JSON value from an input in CBOR format
24437 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24438 template<typename IteratorType>
24439 JSON_HEDLEY_WARN_UNUSED_RESULT
24440 static basic_json from_cbor(IteratorType first, IteratorType last,
24441 const bool strict = true,
24442 const bool allow_exceptions = true,
24443 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24444 {
24445 basic_json result;
24446 auto ia = detail::input_adapter(std::move(first), std::move(last));
24447 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24448 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24449 return res ? result : basic_json(value_t::discarded);
24450 }
24451 
24452 template<typename T>
24453 JSON_HEDLEY_WARN_UNUSED_RESULT
24454 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24455 static basic_json from_cbor(const T* ptr, std::size_t len,
24456 const bool strict = true,
24457 const bool allow_exceptions = true,
24458 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24459 {
24460 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24461 }
24462 
24463 JSON_HEDLEY_WARN_UNUSED_RESULT
24464 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24465 static basic_json from_cbor(detail::span_input_adapter&& i,
24466 const bool strict = true,
24467 const bool allow_exceptions = true,
24468 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24469 {
24470 basic_json result;
24471 auto ia = i.get();
24472 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24473 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24474 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24475 return res ? result : basic_json(value_t::discarded);
24476 }
24477 
24478 /// @brief create a JSON value from an input in MessagePack format
24479 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24480 template<typename InputType>
24481 JSON_HEDLEY_WARN_UNUSED_RESULT
24482 static basic_json from_msgpack(InputType&& i,
24483 const bool strict = true,
24484 const bool allow_exceptions = true)
24485 {
24486 basic_json result;
24487 auto ia = detail::input_adapter(std::forward<InputType>(i));
24488 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24489 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24490 return res ? result : basic_json(value_t::discarded);
24491 }
24492 
24493 /// @brief create a JSON value from an input in MessagePack format
24494 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24495 template<typename IteratorType>
24496 JSON_HEDLEY_WARN_UNUSED_RESULT
24497 static basic_json from_msgpack(IteratorType first, IteratorType last,
24498 const bool strict = true,
24499 const bool allow_exceptions = true)
24500 {
24501 basic_json result;
24502 auto ia = detail::input_adapter(std::move(first), std::move(last));
24503 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24504 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24505 return res ? result : basic_json(value_t::discarded);
24506 }
24507 
24508 template<typename T>
24509 JSON_HEDLEY_WARN_UNUSED_RESULT
24510 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24511 static basic_json from_msgpack(const T* ptr, std::size_t len,
24512 const bool strict = true,
24513 const bool allow_exceptions = true)
24514 {
24515 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24516 }
24517 
24518 JSON_HEDLEY_WARN_UNUSED_RESULT
24519 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24520 static basic_json from_msgpack(detail::span_input_adapter&& i,
24521 const bool strict = true,
24522 const bool allow_exceptions = true)
24523 {
24524 basic_json result;
24525 auto ia = i.get();
24526 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24527 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24528 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24529 return res ? result : basic_json(value_t::discarded);
24530 }
24531 
24532 /// @brief create a JSON value from an input in UBJSON format
24533 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24534 template<typename InputType>
24535 JSON_HEDLEY_WARN_UNUSED_RESULT
24536 static basic_json from_ubjson(InputType&& i,
24537 const bool strict = true,
24538 const bool allow_exceptions = true)
24539 {
24540 basic_json result;
24541 auto ia = detail::input_adapter(std::forward<InputType>(i));
24542 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24543 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24544 return res ? result : basic_json(value_t::discarded);
24545 }
24546 
24547 /// @brief create a JSON value from an input in UBJSON format
24548 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24549 template<typename IteratorType>
24550 JSON_HEDLEY_WARN_UNUSED_RESULT
24551 static basic_json from_ubjson(IteratorType first, IteratorType last,
24552 const bool strict = true,
24553 const bool allow_exceptions = true)
24554 {
24555 basic_json result;
24556 auto ia = detail::input_adapter(std::move(first), std::move(last));
24557 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24558 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24559 return res ? result : basic_json(value_t::discarded);
24560 }
24561 
24562 template<typename T>
24563 JSON_HEDLEY_WARN_UNUSED_RESULT
24564 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24565 static basic_json from_ubjson(const T* ptr, std::size_t len,
24566 const bool strict = true,
24567 const bool allow_exceptions = true)
24568 {
24569 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24570 }
24571 
24572 JSON_HEDLEY_WARN_UNUSED_RESULT
24573 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24574 static basic_json from_ubjson(detail::span_input_adapter&& i,
24575 const bool strict = true,
24576 const bool allow_exceptions = true)
24577 {
24578 basic_json result;
24579 auto ia = i.get();
24580 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24581 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24582 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24583 return res ? result : basic_json(value_t::discarded);
24584 }
24585 
24586 /// @brief create a JSON value from an input in BJData format
24587 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24588 template<typename InputType>
24589 JSON_HEDLEY_WARN_UNUSED_RESULT
24590 static basic_json from_bjdata(InputType&& i,
24591 const bool strict = true,
24592 const bool allow_exceptions = true)
24593 {
24594 basic_json result;
24595 auto ia = detail::input_adapter(std::forward<InputType>(i));
24596 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24597 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24598 return res ? result : basic_json(value_t::discarded);
24599 }
24600 
24601 /// @brief create a JSON value from an input in BJData format
24602 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24603 template<typename IteratorType>
24604 JSON_HEDLEY_WARN_UNUSED_RESULT
24605 static basic_json from_bjdata(IteratorType first, IteratorType last,
24606 const bool strict = true,
24607 const bool allow_exceptions = true)
24608 {
24609 basic_json result;
24610 auto ia = detail::input_adapter(std::move(first), std::move(last));
24611 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24612 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24613 return res ? result : basic_json(value_t::discarded);
24614 }
24615 
24616 /// @brief create a JSON value from an input in BSON format
24617 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24618 template<typename InputType>
24619 JSON_HEDLEY_WARN_UNUSED_RESULT
24620 static basic_json from_bson(InputType&& i,
24621 const bool strict = true,
24622 const bool allow_exceptions = true)
24623 {
24624 basic_json result;
24625 auto ia = detail::input_adapter(std::forward<InputType>(i));
24626 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24627 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24628 return res ? result : basic_json(value_t::discarded);
24629 }
24630 
24631 /// @brief create a JSON value from an input in BSON format
24632 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24633 template<typename IteratorType>
24634 JSON_HEDLEY_WARN_UNUSED_RESULT
24635 static basic_json from_bson(IteratorType first, IteratorType last,
24636 const bool strict = true,
24637 const bool allow_exceptions = true)
24638 {
24639 basic_json result;
24640 auto ia = detail::input_adapter(std::move(first), std::move(last));
24641 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24642 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24643 return res ? result : basic_json(value_t::discarded);
24644 }
24645 
24646 template<typename T>
24647 JSON_HEDLEY_WARN_UNUSED_RESULT
24648 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24649 static basic_json from_bson(const T* ptr, std::size_t len,
24650 const bool strict = true,
24651 const bool allow_exceptions = true)
24652 {
24653 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24654 }
24655 
24656 JSON_HEDLEY_WARN_UNUSED_RESULT
24657 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24658 static basic_json from_bson(detail::span_input_adapter&& i,
24659 const bool strict = true,
24660 const bool allow_exceptions = true)
24661 {
24662 basic_json result;
24663 auto ia = i.get();
24664 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24665 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24666 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24667 return res ? result : basic_json(value_t::discarded);
24668 }
24669 /// @}
24670 
24671 //////////////////////////
24672 // JSON Pointer support //
24673 //////////////////////////
24674 
24675 /// @name JSON Pointer functions
24676 /// @{
24677 
24678 /// @brief access specified element via JSON Pointer
24679 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24680 reference operator[](const json_pointer& ptr)
24681 {
24682 return ptr.get_unchecked(this);
24683 }
24684 
24685 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24686 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24687 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24688 {
24689 return ptr.get_unchecked(this);
24690 }
24691 
24692 /// @brief access specified element via JSON Pointer
24693 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24694 const_reference operator[](const json_pointer& ptr) const
24695 {
24696 return ptr.get_unchecked(this);
24697 }
24698 
24699 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24700 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24701 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24702 {
24703 return ptr.get_unchecked(this);
24704 }
24705 
24706 /// @brief access specified element via JSON Pointer
24707 /// @sa https://json.nlohmann.me/api/basic_json/at/
24708 reference at(const json_pointer& ptr)
24709 {
24710 return ptr.get_checked(this);
24711 }
24712 
24713 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24714 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24715 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24716 {
24717 return ptr.get_checked(this);
24718 }
24719 
24720 /// @brief access specified element via JSON Pointer
24721 /// @sa https://json.nlohmann.me/api/basic_json/at/
24722 const_reference at(const json_pointer& ptr) const
24723 {
24724 return ptr.get_checked(this);
24725 }
24726 
24727 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24728 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24729 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24730 {
24731 return ptr.get_checked(this);
24732 }
24733 
24734 /// @brief return flattened JSON value
24735 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
24736 basic_json flatten() const
24737 {
24738 basic_json result(value_t::object);
24739 json_pointer::flatten("", *this, result);
24740 return result;
24741 }
24742 
24743 /// @brief unflatten a previously flattened JSON value
24744 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
24745 basic_json unflatten() const
24746 {
24747 return json_pointer::unflatten(*this);
24748 }
24749 
24750 /// @}
24751 
24752 //////////////////////////
24753 // JSON Patch functions //
24754 //////////////////////////
24755 
24756 /// @name JSON Patch functions
24757 /// @{
24758 
24759 /// @brief applies a JSON patch in-place without copying the object
24760 /// @sa https://json.nlohmann.me/api/basic_json/patch/
24761 void patch_inplace(const basic_json& json_patch)
24762 {
24763 basic_json& result = *this;
24764 // the valid JSON Patch operations
24765 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24766 
24767 const auto get_op = [](const string_t& op)
24768 {
24769 if (op == "add")
24770 {
24771 return patch_operations::add;
24772 }
24773 if (op == "remove")
24774 {
24775 return patch_operations::remove;
24776 }
24777 if (op == "replace")
24778 {
24779 return patch_operations::replace;
24780 }
24781 if (op == "move")
24782 {
24783 return patch_operations::move;
24784 }
24785 if (op == "copy")
24786 {
24787 return patch_operations::copy;
24788 }
24789 if (op == "test")
24790 {
24791 return patch_operations::test;
24792 }
24793 
24794 return patch_operations::invalid;
24795 };
24796 
24797 // wrapper for "add" operation; add value at ptr
24798 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24799 {
24800 // adding to the root of the target document means replacing it
24801 if (ptr.empty())
24802 {
24803 result = val;
24804 return;
24805 }
24806 
24807 // make sure the top element of the pointer exists
24808 json_pointer const top_pointer = ptr.top();
24809 if (top_pointer != ptr)
24810 {
24811 result.at(top_pointer);
24812 }
24813 
24814 // get reference to parent of JSON pointer ptr
24815 const auto last_path = ptr.back();
24816 ptr.pop_back();
24817 // parent must exist when performing patch add per RFC6902 specs
24818 basic_json& parent = result.at(ptr);
24819 
24820 switch (parent.m_data.m_type)
24821 {
24822 case value_t::null:
24823 case value_t::object:
24824 {
24825 // use operator[] to add value
24826 parent[last_path] = val;
24827 break;
24828 }
24829 
24830 case value_t::array:
24831 {
24832 if (last_path == "-")
24833 {
24834 // special case: append to back
24835 parent.push_back(val);
24836 }
24837 else
24838 {
24839 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24840 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24841 {
24842 // avoid undefined behavior
24843 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24844 }
24845 
24846 // default case: insert add offset
24847 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24848 }
24849 break;
24850 }
24851 
24852 // if there exists a parent it cannot be primitive
24853 case value_t::string: // LCOV_EXCL_LINE
24854 case value_t::boolean: // LCOV_EXCL_LINE
24855 case value_t::number_integer: // LCOV_EXCL_LINE
24856 case value_t::number_unsigned: // LCOV_EXCL_LINE
24857 case value_t::number_float: // LCOV_EXCL_LINE
24858 case value_t::binary: // LCOV_EXCL_LINE
24859 case value_t::discarded: // LCOV_EXCL_LINE
24860 default: // LCOV_EXCL_LINE
24861 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24862 }
24863 };
24864 
24865 // wrapper for "remove" operation; remove value at ptr
24866 const auto operation_remove = [this, & result](json_pointer & ptr)
24867 {
24868 // get reference to parent of JSON pointer ptr
24869 const auto last_path = ptr.back();
24870 ptr.pop_back();
24871 basic_json& parent = result.at(ptr);
24872 
24873 // remove child
24874 if (parent.is_object())
24875 {
24876 // perform range check
24877 auto it = parent.find(last_path);
24878 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24879 {
24880 parent.erase(it);
24881 }
24882 else
24883 {
24884 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24885 }
24886 }
24887 else if (parent.is_array())
24888 {
24889 // note erase performs range check
24890 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24891 }
24892 };
24893 
24894 // type check: top level value must be an array
24895 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24896 {
24897 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24898 }
24899 
24900 // iterate and apply the operations
24901 for (const auto& val : json_patch)
24902 {
24903 // wrapper to get a value for an operation
24904 const auto get_value = [&val](const string_t& op,
24905 const string_t& member,
24906 bool string_type) -> basic_json &
24907 {
24908 // find value
24909 auto it = val.m_data.m_value.object->find(member);
24910 
24911 // context-sensitive error message
24912 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24913 
24914 // check if desired value is present
24915 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24916 {
24917 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24918 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24919 }
24920 
24921 // check if result is of type string
24922 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24923 {
24924 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24925 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24926 }
24927 
24928 // no error: return value
24929 return it->second;
24930 };
24931 
24932 // type check: every element of the array must be an object
24933 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24934 {
24935 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24936 }
24937 
24938 // collect mandatory members
24939 const auto op = get_value("op", "op", true).template get<string_t>();
24940 const auto path = get_value(op, "path", true).template get<string_t>();
24941 json_pointer ptr(path);
24942 
24943 switch (get_op(op))
24944 {
24945 case patch_operations::add:
24946 {
24947 operation_add(ptr, get_value("add", "value", false));
24948 break;
24949 }
24950 
24951 case patch_operations::remove:
24952 {
24953 operation_remove(ptr);
24954 break;
24955 }
24956 
24957 case patch_operations::replace:
24958 {
24959 // the "path" location must exist - use at()
24960 result.at(ptr) = get_value("replace", "value", false);
24961 break;
24962 }
24963 
24964 case patch_operations::move:
24965 {
24966 const auto from_path = get_value("move", "from", true).template get<string_t>();
24967 json_pointer from_ptr(from_path);
24968 
24969 // the "from" location must exist - use at()
24970 basic_json const v = result.at(from_ptr);
24971 
24972 // The move operation is functionally identical to a
24973 // "remove" operation on the "from" location, followed
24974 // immediately by an "add" operation at the target
24975 // location with the value that was just removed.
24976 operation_remove(from_ptr);
24977 operation_add(ptr, v);
24978 break;
24979 }
24980 
24981 case patch_operations::copy:
24982 {
24983 const auto from_path = get_value("copy", "from", true).template get<string_t>();
24984 const json_pointer from_ptr(from_path);
24985 
24986 // the "from" location must exist - use at()
24987 basic_json const v = result.at(from_ptr);
24988 
24989 // The copy is functionally identical to an "add"
24990 // operation at the target location using the value
24991 // specified in the "from" member.
24992 operation_add(ptr, v);
24993 break;
24994 }
24995 
24996 case patch_operations::test:
24997 {
24998 bool success = false;
24999 JSON_TRY
25000 {
25001 // check if "value" matches the one at "path"
25002 // the "path" location must exist - use at()
25003 success = (result.at(ptr) == get_value("test", "value", false));
25004 }
25005 JSON_INTERNAL_CATCH (out_of_range&)
25006 {
25007 // ignore out of range errors: success remains false
25008 }
25009 
25010 // throw an exception if test fails
25011 if (JSON_HEDLEY_UNLIKELY(!success))
25012 {
25013 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25014 }
25015 
25016 break;
25017 }
25018 
25019 case patch_operations::invalid:
25020 default:
25021 {
25022 // op must be "add", "remove", "replace", "move", "copy", or
25023 // "test"
25024 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25025 }
25026 }
25027 }
25028 }
25029 
25030 /// @brief applies a JSON patch to a copy of the current object
25031 /// @sa https://json.nlohmann.me/api/basic_json/patch/
25032 basic_json patch(const basic_json& json_patch) const
25033 {
25034 basic_json result = *this;
25035 result.patch_inplace(json_patch);
25036 return result;
25037 }
25038 
25039 /// @brief creates a diff as a JSON patch
25040 /// @sa https://json.nlohmann.me/api/basic_json/diff/
25041 JSON_HEDLEY_WARN_UNUSED_RESULT
25042 static basic_json diff(const basic_json& source, const basic_json& target,
25043 const string_t& path = "")
25044 {
25045 // the patch
25046 basic_json result(value_t::array);
25047 
25048 // if the values are the same, return empty patch
25049 if (source == target)
25050 {
25051 return result;
25052 }
25053 
25054 if (source.type() != target.type())
25055 {
25056 // different types: replace value
25057 result.push_back(
25058 {
25059 {"op", "replace"}, {"path", path}, {"value", target}
25060 });
25061 return result;
25062 }
25063 
25064 switch (source.type())
25065 {
25066 case value_t::array:
25067 {
25068 // first pass: traverse common elements
25069 std::size_t i = 0;
25070 while (i < source.size() && i < target.size())
25071 {
25072 // recursive call to compare array values at index i
25073 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25074 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25075 ++i;
25076 }
25077 
25078 // We now reached the end of at least one array
25079 // in a second pass, traverse the remaining elements
25080 
25081 // remove my remaining elements
25082 const auto end_index = static_cast<difference_type>(result.size());
25083 while (i < source.size())
25084 {
25085 // add operations in reverse order to avoid invalid
25086 // indices
25087 result.insert(result.begin() + end_index, object(
25088 {
25089 {"op", "remove"},
25090 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25091 }));
25092 ++i;
25093 }
25094 
25095 // add other remaining elements
25096 while (i < target.size())
25097 {
25098 result.push_back(
25099 {
25100 {"op", "add"},
25101 {"path", detail::concat<string_t>(path, "/-")},
25102 {"value", target[i]}
25103 });
25104 ++i;
25105 }
25106 
25107 break;
25108 }
25109 
25110 case value_t::object:
25111 {
25112 // first pass: traverse this object's elements
25113 for (auto it = source.cbegin(); it != source.cend(); ++it)
25114 {
25115 // escape the key name to be used in a JSON patch
25116 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25117 
25118 if (target.find(it.key()) != target.end())
25119 {
25120 // recursive call to compare object values at key it
25121 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25122 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25123 }
25124 else
25125 {
25126 // found a key that is not in o -> remove it
25127 result.push_back(object(
25128 {
25129 {"op", "remove"}, {"path", path_key}
25130 }));
25131 }
25132 }
25133 
25134 // second pass: traverse other object's elements
25135 for (auto it = target.cbegin(); it != target.cend(); ++it)
25136 {
25137 if (source.find(it.key()) == source.end())
25138 {
25139 // found a key that is not in this -> add it
25140 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25141 result.push_back(
25142 {
25143 {"op", "add"}, {"path", path_key},
25144 {"value", it.value()}
25145 });
25146 }
25147 }
25148 
25149 break;
25150 }
25151 
25152 case value_t::null:
25153 case value_t::string:
25154 case value_t::boolean:
25155 case value_t::number_integer:
25156 case value_t::number_unsigned:
25157 case value_t::number_float:
25158 case value_t::binary:
25159 case value_t::discarded:
25160 default:
25161 {
25162 // both primitive type: replace value
25163 result.push_back(
25164 {
25165 {"op", "replace"}, {"path", path}, {"value", target}
25166 });
25167 break;
25168 }
25169 }
25170 
25171 return result;
25172 }
25173 /// @}
25174 
25175 ////////////////////////////////
25176 // JSON Merge Patch functions //
25177 ////////////////////////////////
25178 
25179 /// @name JSON Merge Patch functions
25180 /// @{
25181 
25182 /// @brief applies a JSON Merge Patch
25183 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
25184 void merge_patch(const basic_json& apply_patch)
25185 {
25186 if (apply_patch.is_object())
25187 {
25188 if (!is_object())
25189 {
25190 *this = object();
25191 }
25192 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25193 {
25194 if (it.value().is_null())
25195 {
25196 erase(it.key());
25197 }
25198 else
25199 {
25200 operator[](it.key()).merge_patch(it.value());
25201 }
25202 }
25203 }
25204 else
25205 {
25206 *this = apply_patch;
25207 }
25208 }
25209 
25210 /// @}
25211};
25212 
25213/// @brief user-defined to_string function for JSON values
25214/// @sa https://json.nlohmann.me/api/basic_json/to_string/
25215NLOHMANN_BASIC_JSON_TPL_DECLARATION
25216std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25217{
25218 return j.dump();
25219}
25220 
25221inline namespace literals
25222{
25223inline namespace json_literals
25224{
25225 
25226/// @brief user-defined string literal for JSON values
25227/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
25228JSON_HEDLEY_NON_NULL(1)
25229#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25230 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25231#else
25232 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25233#endif
25234{
25235 return nlohmann::json::parse(s, s + n);
25236}
25237 
25238/// @brief user-defined string literal for JSON pointer
25239/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
25240JSON_HEDLEY_NON_NULL(1)
25241#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25242 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25243#else
25244 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25245#endif
25246{
25247 return nlohmann::json::json_pointer(std::string(s, n));
25248}
25249 
25250} // namespace json_literals
25251} // namespace literals
25252NLOHMANN_JSON_NAMESPACE_END
25253 
25254///////////////////////
25255// nonmember support //
25256///////////////////////
25257 
25258namespace std // NOLINT(cert-dcl58-cpp)
25259{
25260 
25261/// @brief hash value for JSON objects
25262/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
25263NLOHMANN_BASIC_JSON_TPL_DECLARATION
25264struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25265{
25266 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25267 {
25268 return nlohmann::detail::hash(j);
25269 }
25270};
25271 
25272// specialization for std::less<value_t>
25273template<>
25274struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25275{
25276 /*!
25277 @brief compare two value_t enum values
25278 @since version 3.0.0
25279 */
25280 bool operator()(::nlohmann::detail::value_t lhs,
25281 ::nlohmann::detail::value_t rhs) const noexcept
25282 {
25283#if JSON_HAS_THREE_WAY_COMPARISON
25284 return std::is_lt(lhs <=> rhs); // *NOPAD*
25285#else
25286 return ::nlohmann::detail::operator<(lhs, rhs);
25287#endif
25288 }
25289};
25290 
25291// C++20 prohibit function specialization in the std namespace.
25292#ifndef JSON_HAS_CPP_20
25293 
25294/// @brief exchanges the values of two JSON objects
25295/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
25296NLOHMANN_BASIC_JSON_TPL_DECLARATION
25297inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25298 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25299 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25300{
25301 j1.swap(j2);
25302}
25303 
25304#endif
25305 
25306} // namespace std
25307 
25308#if JSON_USE_GLOBAL_UDLS
25309 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25310 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25311 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25312 #else
25313 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25314 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25315 #endif
25316#endif
25317 
25318// #include <nlohmann/detail/macro_unscope.hpp>
25319// __ _____ _____ _____
25320// __| | __| | | | JSON for Modern C++
25321// | | |__ | | | | | | version 3.12.0
25322// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25323//
25324// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25325// SPDX-License-Identifier: MIT
25326 
25327 
25328 
25329// restore clang diagnostic settings
25330#if defined(__clang__)
25331 #pragma clang diagnostic pop
25332#endif
25333 
25334// clean up
25335#undef JSON_ASSERT
25336#undef JSON_INTERNAL_CATCH
25337#undef JSON_THROW
25338#undef JSON_PRIVATE_UNLESS_TESTED
25339#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25340#undef NLOHMANN_BASIC_JSON_TPL
25341#undef JSON_EXPLICIT
25342#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25343#undef JSON_INLINE_VARIABLE
25344#undef JSON_NO_UNIQUE_ADDRESS
25345#undef JSON_DISABLE_ENUM_SERIALIZATION
25346#undef JSON_USE_GLOBAL_UDLS
25347 
25348#ifndef JSON_TEST_KEEP_MACROS
25349 #undef JSON_CATCH
25350 #undef JSON_TRY
25351 #undef JSON_HAS_CPP_11
25352 #undef JSON_HAS_CPP_14
25353 #undef JSON_HAS_CPP_17
25354 #undef JSON_HAS_CPP_20
25355 #undef JSON_HAS_CPP_23
25356 #undef JSON_HAS_FILESYSTEM
25357 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25358 #undef JSON_HAS_THREE_WAY_COMPARISON
25359 #undef JSON_HAS_RANGES
25360 #undef JSON_HAS_STATIC_RTTI
25361 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25362#endif
25363 
25364// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25365// __ _____ _____ _____
25366// __| | __| | | | JSON for Modern C++
25367// | | |__ | | | | | | version 3.12.0
25368// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25369//
25370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25371// SPDX-License-Identifier: MIT
25372 
25373 
25374 
25375#undef JSON_HEDLEY_ALWAYS_INLINE
25376#undef JSON_HEDLEY_ARM_VERSION
25377#undef JSON_HEDLEY_ARM_VERSION_CHECK
25378#undef JSON_HEDLEY_ARRAY_PARAM
25379#undef JSON_HEDLEY_ASSUME
25380#undef JSON_HEDLEY_BEGIN_C_DECLS
25381#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25382#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25383#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25384#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25385#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25386#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25387#undef JSON_HEDLEY_CLANG_HAS_WARNING
25388#undef JSON_HEDLEY_COMPCERT_VERSION
25389#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25390#undef JSON_HEDLEY_CONCAT
25391#undef JSON_HEDLEY_CONCAT3
25392#undef JSON_HEDLEY_CONCAT3_EX
25393#undef JSON_HEDLEY_CONCAT_EX
25394#undef JSON_HEDLEY_CONST
25395#undef JSON_HEDLEY_CONSTEXPR
25396#undef JSON_HEDLEY_CONST_CAST
25397#undef JSON_HEDLEY_CPP_CAST
25398#undef JSON_HEDLEY_CRAY_VERSION
25399#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25400#undef JSON_HEDLEY_C_DECL
25401#undef JSON_HEDLEY_DEPRECATED
25402#undef JSON_HEDLEY_DEPRECATED_FOR
25403#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25404#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25405#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25406#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25407#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25408#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25409#undef JSON_HEDLEY_DIAGNOSTIC_POP
25410#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25411#undef JSON_HEDLEY_DMC_VERSION
25412#undef JSON_HEDLEY_DMC_VERSION_CHECK
25413#undef JSON_HEDLEY_EMPTY_BASES
25414#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25415#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25416#undef JSON_HEDLEY_END_C_DECLS
25417#undef JSON_HEDLEY_FLAGS
25418#undef JSON_HEDLEY_FLAGS_CAST
25419#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25420#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25421#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25422#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25423#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25424#undef JSON_HEDLEY_GCC_HAS_FEATURE
25425#undef JSON_HEDLEY_GCC_HAS_WARNING
25426#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25427#undef JSON_HEDLEY_GCC_VERSION
25428#undef JSON_HEDLEY_GCC_VERSION_CHECK
25429#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25430#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25431#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25432#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25433#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25434#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25435#undef JSON_HEDLEY_GNUC_HAS_WARNING
25436#undef JSON_HEDLEY_GNUC_VERSION
25437#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25438#undef JSON_HEDLEY_HAS_ATTRIBUTE
25439#undef JSON_HEDLEY_HAS_BUILTIN
25440#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25441#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25442#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25443#undef JSON_HEDLEY_HAS_EXTENSION
25444#undef JSON_HEDLEY_HAS_FEATURE
25445#undef JSON_HEDLEY_HAS_WARNING
25446#undef JSON_HEDLEY_IAR_VERSION
25447#undef JSON_HEDLEY_IAR_VERSION_CHECK
25448#undef JSON_HEDLEY_IBM_VERSION
25449#undef JSON_HEDLEY_IBM_VERSION_CHECK
25450#undef JSON_HEDLEY_IMPORT
25451#undef JSON_HEDLEY_INLINE
25452#undef JSON_HEDLEY_INTEL_CL_VERSION
25453#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25454#undef JSON_HEDLEY_INTEL_VERSION
25455#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25456#undef JSON_HEDLEY_IS_CONSTANT
25457#undef JSON_HEDLEY_IS_CONSTEXPR_
25458#undef JSON_HEDLEY_LIKELY
25459#undef JSON_HEDLEY_MALLOC
25460#undef JSON_HEDLEY_MCST_LCC_VERSION
25461#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25462#undef JSON_HEDLEY_MESSAGE
25463#undef JSON_HEDLEY_MSVC_VERSION
25464#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25465#undef JSON_HEDLEY_NEVER_INLINE
25466#undef JSON_HEDLEY_NON_NULL
25467#undef JSON_HEDLEY_NO_ESCAPE
25468#undef JSON_HEDLEY_NO_RETURN
25469#undef JSON_HEDLEY_NO_THROW
25470#undef JSON_HEDLEY_NULL
25471#undef JSON_HEDLEY_PELLES_VERSION
25472#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25473#undef JSON_HEDLEY_PGI_VERSION
25474#undef JSON_HEDLEY_PGI_VERSION_CHECK
25475#undef JSON_HEDLEY_PREDICT
25476#undef JSON_HEDLEY_PRINTF_FORMAT
25477#undef JSON_HEDLEY_PRIVATE
25478#undef JSON_HEDLEY_PUBLIC
25479#undef JSON_HEDLEY_PURE
25480#undef JSON_HEDLEY_REINTERPRET_CAST
25481#undef JSON_HEDLEY_REQUIRE
25482#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25483#undef JSON_HEDLEY_REQUIRE_MSG
25484#undef JSON_HEDLEY_RESTRICT
25485#undef JSON_HEDLEY_RETURNS_NON_NULL
25486#undef JSON_HEDLEY_SENTINEL
25487#undef JSON_HEDLEY_STATIC_ASSERT
25488#undef JSON_HEDLEY_STATIC_CAST
25489#undef JSON_HEDLEY_STRINGIFY
25490#undef JSON_HEDLEY_STRINGIFY_EX
25491#undef JSON_HEDLEY_SUNPRO_VERSION
25492#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25493#undef JSON_HEDLEY_TINYC_VERSION
25494#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25495#undef JSON_HEDLEY_TI_ARMCL_VERSION
25496#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25497#undef JSON_HEDLEY_TI_CL2000_VERSION
25498#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25499#undef JSON_HEDLEY_TI_CL430_VERSION
25500#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25501#undef JSON_HEDLEY_TI_CL6X_VERSION
25502#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25503#undef JSON_HEDLEY_TI_CL7X_VERSION
25504#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25505#undef JSON_HEDLEY_TI_CLPRU_VERSION
25506#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25507#undef JSON_HEDLEY_TI_VERSION
25508#undef JSON_HEDLEY_TI_VERSION_CHECK
25509#undef JSON_HEDLEY_UNAVAILABLE
25510#undef JSON_HEDLEY_UNLIKELY
25511#undef JSON_HEDLEY_UNPREDICTABLE
25512#undef JSON_HEDLEY_UNREACHABLE
25513#undef JSON_HEDLEY_UNREACHABLE_RETURN
25514#undef JSON_HEDLEY_VERSION
25515#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25516#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25517#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25518#undef JSON_HEDLEY_VERSION_ENCODE
25519#undef JSON_HEDLEY_WARNING
25520#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25521#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25522#undef JSON_HEDLEY_FALL_THROUGH
25523 
25524 
25525 
25526#endif // INCLUDE_NLOHMANN_JSON_HPP_
25527