OpenAstra
 
Loading...
Searching...
No Matches
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#include <string> // string
177#include <tuple> // tuple, make_tuple
178#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
179#include <unordered_map> // unordered_map
180#include <utility> // pair, declval
181#include <valarray> // valarray
182
183// #include <nlohmann/detail/exceptions.hpp>
184// __ _____ _____ _____
185// __| | __| | | | JSON for Modern C++
186// | | |__ | | | | | | version 3.12.0
187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
188//
189// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
190// SPDX-License-Identifier: MIT
191
192
193
194#include <cstddef> // nullptr_t
195#include <exception> // exception
196#if JSON_DIAGNOSTICS
197 #include <numeric> // accumulate
198#endif
199#include <stdexcept> // runtime_error
200#include <string> // to_string
201#include <vector> // vector
202
203// #include <nlohmann/detail/value_t.hpp>
204// __ _____ _____ _____
205// __| | __| | | | JSON for Modern C++
206// | | |__ | | | | | | version 3.12.0
207// |_____|_____|_____|_|___| https://github.com/nlohmann/json
208//
209// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
210// SPDX-License-Identifier: MIT
211
212
213
214#include <array> // array
215#include <cstddef> // size_t
216#include <cstdint> // uint8_t
217#include <string> // string
218
219// #include <nlohmann/detail/macro_scope.hpp>
220// __ _____ _____ _____
221// __| | __| | | | JSON for Modern C++
222// | | |__ | | | | | | version 3.12.0
223// |_____|_____|_____|_|___| https://github.com/nlohmann/json
224//
225// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
226// SPDX-License-Identifier: MIT
227
228
229
230#include <utility> // declval, pair
231// #include <nlohmann/detail/meta/detected.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.12.0
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242#include <type_traits>
243
244// #include <nlohmann/detail/meta/void_t.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.12.0
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
258NLOHMANN_JSON_NAMESPACE_BEGIN
259namespace detail
260{
261
262template<typename ...Ts> struct make_void
263{
264 using type = void;
265};
266template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
267
268} // namespace detail
269NLOHMANN_JSON_NAMESPACE_END
270
271
272NLOHMANN_JSON_NAMESPACE_BEGIN
273namespace detail
274{
275
276// https://en.cppreference.com/w/cpp/experimental/is_detected
277struct nonesuch
278{
279 nonesuch() = delete;
280 ~nonesuch() = delete;
281 nonesuch(nonesuch const&) = delete;
282 nonesuch(nonesuch const&&) = delete;
283 void operator=(nonesuch const&) = delete;
284 void operator=(nonesuch&&) = delete;
285};
286
287template<class Default,
288 class AlwaysVoid,
289 template<class...> class Op,
290 class... Args>
292{
293 using value_t = std::false_type;
294 using type = Default;
295};
296
297template<class Default, template<class...> class Op, class... Args>
298struct detector<Default, void_t<Op<Args...>>, Op, Args...>
299{
300 using value_t = std::true_type;
301 using type = Op<Args...>;
302};
303
304template<template<class...> class Op, class... Args>
305using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
306
307template<template<class...> class Op, class... Args>
308struct is_detected_lazy : is_detected<Op, Args...> { };
309
310template<template<class...> class Op, class... Args>
311using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
312
313template<class Default, template<class...> class Op, class... Args>
314using detected_or = detector<Default, void, Op, Args...>;
315
316template<class Default, template<class...> class Op, class... Args>
317using detected_or_t = typename detected_or<Default, Op, Args...>::type;
318
319template<class Expected, template<class...> class Op, class... Args>
320using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
321
322template<class To, template<class...> class Op, class... Args>
323using is_detected_convertible =
324 std::is_convertible<detected_t<Op, Args...>, To>;
325
326} // namespace detail
327NLOHMANN_JSON_NAMESPACE_END
328
329// #include <nlohmann/thirdparty/hedley/hedley.hpp>
330
331
332// __ _____ _____ _____
333// __| | __| | | | JSON for Modern C++
334// | | |__ | | | | | | version 3.12.0
335// |_____|_____|_____|_|___| https://github.com/nlohmann/json
336//
337// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
338// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
339// SPDX-License-Identifier: MIT
340
341/* Hedley - https://nemequ.github.io/hedley
342 * Created by Evan Nemerson <evan@nemerson.com>
343 * SPDX-License-Identifier: CC0-1.0
344 */
345
346#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
347#if defined(JSON_HEDLEY_VERSION)
348 #undef JSON_HEDLEY_VERSION
349#endif
350#define JSON_HEDLEY_VERSION 15
351
352#if defined(JSON_HEDLEY_STRINGIFY_EX)
353 #undef JSON_HEDLEY_STRINGIFY_EX
354#endif
355#define JSON_HEDLEY_STRINGIFY_EX(x) #x
356
357#if defined(JSON_HEDLEY_STRINGIFY)
358 #undef JSON_HEDLEY_STRINGIFY
359#endif
360#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
361
362#if defined(JSON_HEDLEY_CONCAT_EX)
363 #undef JSON_HEDLEY_CONCAT_EX
364#endif
365#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
366
367#if defined(JSON_HEDLEY_CONCAT)
368 #undef JSON_HEDLEY_CONCAT
369#endif
370#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
371
372#if defined(JSON_HEDLEY_CONCAT3_EX)
373 #undef JSON_HEDLEY_CONCAT3_EX
374#endif
375#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
376
377#if defined(JSON_HEDLEY_CONCAT3)
378 #undef JSON_HEDLEY_CONCAT3
379#endif
380#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
381
382#if defined(JSON_HEDLEY_VERSION_ENCODE)
383 #undef JSON_HEDLEY_VERSION_ENCODE
384#endif
385#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
386
387#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
388 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
389#endif
390#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
391
392#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
393 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
394#endif
395#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
396
397#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
398 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
399#endif
400#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
401
402#if defined(JSON_HEDLEY_GNUC_VERSION)
403 #undef JSON_HEDLEY_GNUC_VERSION
404#endif
405#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
406 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
407#elif defined(__GNUC__)
408 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
409#endif
410
411#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
412 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
413#endif
414#if defined(JSON_HEDLEY_GNUC_VERSION)
415 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
416#else
417 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
418#endif
419
420#if defined(JSON_HEDLEY_MSVC_VERSION)
421 #undef JSON_HEDLEY_MSVC_VERSION
422#endif
423#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
424 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
425#elif defined(_MSC_FULL_VER) && !defined(__ICL)
426 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
427#elif defined(_MSC_VER) && !defined(__ICL)
428 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
429#endif
430
431#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
432 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
433#endif
434#if !defined(JSON_HEDLEY_MSVC_VERSION)
435 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
436#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
437 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
438#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
439 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
440#else
441 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
442#endif
443
444#if defined(JSON_HEDLEY_INTEL_VERSION)
445 #undef JSON_HEDLEY_INTEL_VERSION
446#endif
447#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
448 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
449#elif defined(__INTEL_COMPILER) && !defined(__ICL)
450 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
451#endif
452
453#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
454 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
455#endif
456#if defined(JSON_HEDLEY_INTEL_VERSION)
457 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
458#else
459 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
460#endif
461
462#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
463 #undef JSON_HEDLEY_INTEL_CL_VERSION
464#endif
465#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
466 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
467#endif
468
469#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
470 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
471#endif
472#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
473 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
474#else
475 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
476#endif
477
478#if defined(JSON_HEDLEY_PGI_VERSION)
479 #undef JSON_HEDLEY_PGI_VERSION
480#endif
481#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
482 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
483#endif
484
485#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
486 #undef JSON_HEDLEY_PGI_VERSION_CHECK
487#endif
488#if defined(JSON_HEDLEY_PGI_VERSION)
489 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
490#else
491 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
492#endif
493
494#if defined(JSON_HEDLEY_SUNPRO_VERSION)
495 #undef JSON_HEDLEY_SUNPRO_VERSION
496#endif
497#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
498 #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)
499#elif defined(__SUNPRO_C)
500 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
501#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
502 #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)
503#elif defined(__SUNPRO_CC)
504 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
505#endif
506
507#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
508 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
509#endif
510#if defined(JSON_HEDLEY_SUNPRO_VERSION)
511 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
512#else
513 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
514#endif
515
516#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
517 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
518#endif
519#if defined(__EMSCRIPTEN__)
520 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
521#endif
522
523#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
524 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
525#endif
526#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
527 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
528#else
529 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
530#endif
531
532#if defined(JSON_HEDLEY_ARM_VERSION)
533 #undef JSON_HEDLEY_ARM_VERSION
534#endif
535#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
536 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
537#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
538 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
539#endif
540
541#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
542 #undef JSON_HEDLEY_ARM_VERSION_CHECK
543#endif
544#if defined(JSON_HEDLEY_ARM_VERSION)
545 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
546#else
547 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
548#endif
549
550#if defined(JSON_HEDLEY_IBM_VERSION)
551 #undef JSON_HEDLEY_IBM_VERSION
552#endif
553#if defined(__ibmxl__)
554 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
555#elif defined(__xlC__) && defined(__xlC_ver__)
556 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
557#elif defined(__xlC__)
558 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
559#endif
560
561#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
562 #undef JSON_HEDLEY_IBM_VERSION_CHECK
563#endif
564#if defined(JSON_HEDLEY_IBM_VERSION)
565 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
566#else
567 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
568#endif
569
570#if defined(JSON_HEDLEY_TI_VERSION)
571 #undef JSON_HEDLEY_TI_VERSION
572#endif
573#if \
574 defined(__TI_COMPILER_VERSION__) && \
575 ( \
576 defined(__TMS470__) || defined(__TI_ARM__) || \
577 defined(__MSP430__) || \
578 defined(__TMS320C2000__) \
579 )
580#if (__TI_COMPILER_VERSION__ >= 16000000)
581 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
582#endif
583#endif
584
585#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
586 #undef JSON_HEDLEY_TI_VERSION_CHECK
587#endif
588#if defined(JSON_HEDLEY_TI_VERSION)
589 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
590#else
591 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
592#endif
593
594#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
595 #undef JSON_HEDLEY_TI_CL2000_VERSION
596#endif
597#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
598 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
599#endif
600
601#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
602 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
603#endif
604#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
605 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
606#else
607 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
608#endif
609
610#if defined(JSON_HEDLEY_TI_CL430_VERSION)
611 #undef JSON_HEDLEY_TI_CL430_VERSION
612#endif
613#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
614 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
615#endif
616
617#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
618 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
619#endif
620#if defined(JSON_HEDLEY_TI_CL430_VERSION)
621 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
622#else
623 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
624#endif
625
626#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
627 #undef JSON_HEDLEY_TI_ARMCL_VERSION
628#endif
629#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
630 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
631#endif
632
633#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
634 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
635#endif
636#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
637 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
638#else
639 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
640#endif
641
642#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
643 #undef JSON_HEDLEY_TI_CL6X_VERSION
644#endif
645#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
646 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
647#endif
648
649#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
650 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
651#endif
652#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
653 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
654#else
655 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
656#endif
657
658#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
659 #undef JSON_HEDLEY_TI_CL7X_VERSION
660#endif
661#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
662 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
663#endif
664
665#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
666 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
667#endif
668#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
669 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
670#else
671 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
672#endif
673
674#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
675 #undef JSON_HEDLEY_TI_CLPRU_VERSION
676#endif
677#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
678 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
679#endif
680
681#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
682 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
683#endif
684#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
685 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
686#else
687 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
688#endif
689
690#if defined(JSON_HEDLEY_CRAY_VERSION)
691 #undef JSON_HEDLEY_CRAY_VERSION
692#endif
693#if defined(_CRAYC)
694 #if defined(_RELEASE_PATCHLEVEL)
695 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
696 #else
697 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
698 #endif
699#endif
700
701#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
702 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
703#endif
704#if defined(JSON_HEDLEY_CRAY_VERSION)
705 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
706#else
707 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
708#endif
709
710#if defined(JSON_HEDLEY_IAR_VERSION)
711 #undef JSON_HEDLEY_IAR_VERSION
712#endif
713#if defined(__IAR_SYSTEMS_ICC__)
714 #if __VER__ > 1000
715 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
716 #else
717 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
718 #endif
719#endif
720
721#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
722 #undef JSON_HEDLEY_IAR_VERSION_CHECK
723#endif
724#if defined(JSON_HEDLEY_IAR_VERSION)
725 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
726#else
727 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
728#endif
729
730#if defined(JSON_HEDLEY_TINYC_VERSION)
731 #undef JSON_HEDLEY_TINYC_VERSION
732#endif
733#if defined(__TINYC__)
734 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
735#endif
736
737#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
738 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
739#endif
740#if defined(JSON_HEDLEY_TINYC_VERSION)
741 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
742#else
743 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
744#endif
745
746#if defined(JSON_HEDLEY_DMC_VERSION)
747 #undef JSON_HEDLEY_DMC_VERSION
748#endif
749#if defined(__DMC__)
750 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
751#endif
752
753#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
754 #undef JSON_HEDLEY_DMC_VERSION_CHECK
755#endif
756#if defined(JSON_HEDLEY_DMC_VERSION)
757 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
758#else
759 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
760#endif
761
762#if defined(JSON_HEDLEY_COMPCERT_VERSION)
763 #undef JSON_HEDLEY_COMPCERT_VERSION
764#endif
765#if defined(__COMPCERT_VERSION__)
766 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
767#endif
768
769#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
770 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
771#endif
772#if defined(JSON_HEDLEY_COMPCERT_VERSION)
773 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
774#else
775 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
776#endif
777
778#if defined(JSON_HEDLEY_PELLES_VERSION)
779 #undef JSON_HEDLEY_PELLES_VERSION
780#endif
781#if defined(__POCC__)
782 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
783#endif
784
785#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
786 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
787#endif
788#if defined(JSON_HEDLEY_PELLES_VERSION)
789 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
790#else
791 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
792#endif
793
794#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
795 #undef JSON_HEDLEY_MCST_LCC_VERSION
796#endif
797#if defined(__LCC__) && defined(__LCC_MINOR__)
798 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
799#endif
800
801#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
802 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
803#endif
804#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
805 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
806#else
807 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
808#endif
809
810#if defined(JSON_HEDLEY_GCC_VERSION)
811 #undef JSON_HEDLEY_GCC_VERSION
812#endif
813#if \
814 defined(JSON_HEDLEY_GNUC_VERSION) && \
815 !defined(__clang__) && \
816 !defined(JSON_HEDLEY_INTEL_VERSION) && \
817 !defined(JSON_HEDLEY_PGI_VERSION) && \
818 !defined(JSON_HEDLEY_ARM_VERSION) && \
819 !defined(JSON_HEDLEY_CRAY_VERSION) && \
820 !defined(JSON_HEDLEY_TI_VERSION) && \
821 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
822 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
823 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
827 !defined(__COMPCERT__) && \
828 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
829 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
830#endif
831
832#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
833 #undef JSON_HEDLEY_GCC_VERSION_CHECK
834#endif
835#if defined(JSON_HEDLEY_GCC_VERSION)
836 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
837#else
838 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
839#endif
840
841#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
842 #undef JSON_HEDLEY_HAS_ATTRIBUTE
843#endif
844#if \
845 defined(__has_attribute) && \
846 ( \
847 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
848 )
849# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
850#else
851# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
852#endif
853
854#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
855 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
856#endif
857#if defined(__has_attribute)
858 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
859#else
860 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
861#endif
862
863#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
864 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
865#endif
866#if defined(__has_attribute)
867 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
868#else
869 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
870#endif
871
872#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
873 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
874#endif
875#if \
876 defined(__has_cpp_attribute) && \
877 defined(__cplusplus) && \
878 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
879 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
880#else
881 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
882#endif
883
884#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
885 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
886#endif
887#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
888 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
889#elif \
890 !defined(JSON_HEDLEY_PGI_VERSION) && \
891 !defined(JSON_HEDLEY_IAR_VERSION) && \
892 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
893 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
894 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
895#else
896 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
897#endif
898
899#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
900 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
901#endif
902#if defined(__has_cpp_attribute) && defined(__cplusplus)
903 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
904#else
905 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
906#endif
907
908#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
909 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
910#endif
911#if defined(__has_cpp_attribute) && defined(__cplusplus)
912 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
913#else
914 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
915#endif
916
917#if defined(JSON_HEDLEY_HAS_BUILTIN)
918 #undef JSON_HEDLEY_HAS_BUILTIN
919#endif
920#if defined(__has_builtin)
921 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
922#else
923 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
924#endif
925
926#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
927 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
928#endif
929#if defined(__has_builtin)
930 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
931#else
932 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
933#endif
934
935#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
936 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
937#endif
938#if defined(__has_builtin)
939 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
940#else
941 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
942#endif
943
944#if defined(JSON_HEDLEY_HAS_FEATURE)
945 #undef JSON_HEDLEY_HAS_FEATURE
946#endif
947#if defined(__has_feature)
948 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
949#else
950 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
951#endif
952
953#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
954 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
955#endif
956#if defined(__has_feature)
957 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
958#else
959 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
960#endif
961
962#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
963 #undef JSON_HEDLEY_GCC_HAS_FEATURE
964#endif
965#if defined(__has_feature)
966 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
967#else
968 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
969#endif
970
971#if defined(JSON_HEDLEY_HAS_EXTENSION)
972 #undef JSON_HEDLEY_HAS_EXTENSION
973#endif
974#if defined(__has_extension)
975 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
976#else
977 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
978#endif
979
980#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
981 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
982#endif
983#if defined(__has_extension)
984 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
985#else
986 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
987#endif
988
989#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
990 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
991#endif
992#if defined(__has_extension)
993 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
994#else
995 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
996#endif
997
998#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
999 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1000#endif
1001#if defined(__has_declspec_attribute)
1002 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1003#else
1004 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1005#endif
1006
1007#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1008 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1009#endif
1010#if defined(__has_declspec_attribute)
1011 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1012#else
1013 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1014#endif
1015
1016#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1017 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1018#endif
1019#if defined(__has_declspec_attribute)
1020 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1021#else
1022 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1023#endif
1024
1025#if defined(JSON_HEDLEY_HAS_WARNING)
1026 #undef JSON_HEDLEY_HAS_WARNING
1027#endif
1028#if defined(__has_warning)
1029 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1030#else
1031 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1032#endif
1033
1034#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1035 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1036#endif
1037#if defined(__has_warning)
1038 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1039#else
1040 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1041#endif
1042
1043#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1044 #undef JSON_HEDLEY_GCC_HAS_WARNING
1045#endif
1046#if defined(__has_warning)
1047 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1048#else
1049 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1050#endif
1051
1052#if \
1053 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1054 defined(__clang__) || \
1055 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1056 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1057 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1058 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1059 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1060 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1061 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1062 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1063 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1064 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1065 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1066 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1067 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1068 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1069 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1070 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1071 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1072#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1073 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1074#else
1075 #define JSON_HEDLEY_PRAGMA(value)
1076#endif
1077
1078#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1079 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1080#endif
1081#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1082 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1083#endif
1084#if defined(__clang__)
1085 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1086 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1087#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1088 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1089 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1090#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1091 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1092 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1093#elif \
1094 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1095 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1097 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1098#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1101#elif \
1102 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1103 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1104 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1105 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1106 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1107 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1108 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1109 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1110#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1111 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1112 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1113#else
1114 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1115 #define JSON_HEDLEY_DIAGNOSTIC_POP
1116#endif
1117
1118/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1119 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1120#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1121 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1122#endif
1123#if defined(__cplusplus)
1124# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1125# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1126# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1127# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1128 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1129 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1131 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1132 xpr \
1133 JSON_HEDLEY_DIAGNOSTIC_POP
1134# else
1135# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1136 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1137 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1138 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1139 xpr \
1140 JSON_HEDLEY_DIAGNOSTIC_POP
1141# endif
1142# else
1143# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1144 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1145 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1146 xpr \
1147 JSON_HEDLEY_DIAGNOSTIC_POP
1148# endif
1149# endif
1150#endif
1151#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1152 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1153#endif
1154
1155#if defined(JSON_HEDLEY_CONST_CAST)
1156 #undef JSON_HEDLEY_CONST_CAST
1157#endif
1158#if defined(__cplusplus)
1159# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1160#elif \
1161 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1162 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1163 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1164# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1165 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1166 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1167 ((T) (expr)); \
1168 JSON_HEDLEY_DIAGNOSTIC_POP \
1169 }))
1170#else
1171# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1172#endif
1173
1174#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1175 #undef JSON_HEDLEY_REINTERPRET_CAST
1176#endif
1177#if defined(__cplusplus)
1178 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1179#else
1180 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1181#endif
1182
1183#if defined(JSON_HEDLEY_STATIC_CAST)
1184 #undef JSON_HEDLEY_STATIC_CAST
1185#endif
1186#if defined(__cplusplus)
1187 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1188#else
1189 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1190#endif
1191
1192#if defined(JSON_HEDLEY_CPP_CAST)
1193 #undef JSON_HEDLEY_CPP_CAST
1194#endif
1195#if defined(__cplusplus)
1196# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1197# define JSON_HEDLEY_CPP_CAST(T, expr) \
1198 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1199 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1200 ((T) (expr)) \
1201 JSON_HEDLEY_DIAGNOSTIC_POP
1202# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1203# define JSON_HEDLEY_CPP_CAST(T, expr) \
1204 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1205 _Pragma("diag_suppress=Pe137") \
1206 JSON_HEDLEY_DIAGNOSTIC_POP
1207# else
1208# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1209# endif
1210#else
1211# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1212#endif
1213
1214#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1215 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1216#endif
1217#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1219#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1221#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1223#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1225#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1226 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1227#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1228 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1229#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1231#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1233#elif \
1234 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1235 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1236 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1237 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1238 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1239 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1240 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1241 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1242 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1243 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1244 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1245 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1246#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1249 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1250#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1251 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1252#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1253 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1254#else
1255 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1256#endif
1257
1258#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1259 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1260#endif
1261#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1262 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1263#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1265#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1267#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1269#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1271#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1273#elif \
1274 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1275 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1276 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1277 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1279#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1281#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1283#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1285#else
1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1287#endif
1288
1289#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1290 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1291#endif
1292#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1294#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1296#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1298#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1300#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1301 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1302#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1303 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1304#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1306#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1308#elif \
1309 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1310 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1311 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1312 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1313#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1314 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1315#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1317#else
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1319#endif
1320
1321#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1322 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1323#endif
1324#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1325 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1326#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1327 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1328#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1330#else
1331 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1332#endif
1333
1334#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1335 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1336#endif
1337#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1338 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1339#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1340 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1341#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1343#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1344 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1345#else
1346 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1347#endif
1348
1349#if defined(JSON_HEDLEY_DEPRECATED)
1350 #undef JSON_HEDLEY_DEPRECATED
1351#endif
1352#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1353 #undef JSON_HEDLEY_DEPRECATED_FOR
1354#endif
1355#if \
1356 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1357 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1358 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1359 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1360#elif \
1361 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1362 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1363 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1364 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1365 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1366 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1367 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1368 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1369 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1370 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1371 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1372 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1373 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1374 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1375#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1376 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1377 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1378#elif \
1379 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1380 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1381 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1382 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1383 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1384 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1385 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1386 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1387 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1388 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1389 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1390 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1391 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1392 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1393 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1394 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1395 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1396 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1397#elif \
1398 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1399 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1400 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1401 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1402 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1403#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1404 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1405 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1406#else
1407 #define JSON_HEDLEY_DEPRECATED(since)
1408 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1409#endif
1410
1411#if defined(JSON_HEDLEY_UNAVAILABLE)
1412 #undef JSON_HEDLEY_UNAVAILABLE
1413#endif
1414#if \
1415 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1416 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1417 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1418 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1419 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1420#else
1421 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1422#endif
1423
1424#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1425 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1426#endif
1427#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1428 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1429#endif
1430#if \
1431 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1432 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1433 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1434 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1435 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1436 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1437 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1439 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1441 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1443 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1444 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1445 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1446 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1447 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1450#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1453#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1455 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1456#elif defined(_Check_return_) /* SAL */
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1458 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1459#else
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1461 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1462#endif
1463
1464#if defined(JSON_HEDLEY_SENTINEL)
1465 #undef JSON_HEDLEY_SENTINEL
1466#endif
1467#if \
1468 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1469 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1470 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1471 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1472 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1473 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1474#else
1475 #define JSON_HEDLEY_SENTINEL(position)
1476#endif
1477
1478#if defined(JSON_HEDLEY_NO_RETURN)
1479 #undef JSON_HEDLEY_NO_RETURN
1480#endif
1481#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1482 #define JSON_HEDLEY_NO_RETURN __noreturn
1483#elif \
1484 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1485 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1486 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1487#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1488 #define JSON_HEDLEY_NO_RETURN _Noreturn
1489#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1490 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1491#elif \
1492 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1493 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1494 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1495 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1496 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1497 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1498 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1499 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1500 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1501 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1502 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1503 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1504 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1505 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1506 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1507 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1508 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1509 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1510#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1511 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1512#elif \
1513 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1514 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1515 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1516#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1517 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1518#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1519 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1520#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1521 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1522#else
1523 #define JSON_HEDLEY_NO_RETURN
1524#endif
1525
1526#if defined(JSON_HEDLEY_NO_ESCAPE)
1527 #undef JSON_HEDLEY_NO_ESCAPE
1528#endif
1529#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1530 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1531#else
1532 #define JSON_HEDLEY_NO_ESCAPE
1533#endif
1534
1535#if defined(JSON_HEDLEY_UNREACHABLE)
1536 #undef JSON_HEDLEY_UNREACHABLE
1537#endif
1538#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1539 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1540#endif
1541#if defined(JSON_HEDLEY_ASSUME)
1542 #undef JSON_HEDLEY_ASSUME
1543#endif
1544#if \
1545 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1546 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1547 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1548 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1549#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1550 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1551#elif \
1552 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1553 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1554 #if defined(__cplusplus)
1555 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1556 #else
1557 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1558 #endif
1559#endif
1560#if \
1561 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1562 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1563 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1564 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1565 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1566 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1567 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1568 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1569#elif defined(JSON_HEDLEY_ASSUME)
1570 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1571#endif
1572#if !defined(JSON_HEDLEY_ASSUME)
1573 #if defined(JSON_HEDLEY_UNREACHABLE)
1574 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1575 #else
1576 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1577 #endif
1578#endif
1579#if defined(JSON_HEDLEY_UNREACHABLE)
1580 #if \
1581 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1582 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1583 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1584 #else
1585 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1586 #endif
1587#else
1588 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1589#endif
1590#if !defined(JSON_HEDLEY_UNREACHABLE)
1591 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1592#endif
1593
1594JSON_HEDLEY_DIAGNOSTIC_PUSH
1595#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1596 #pragma clang diagnostic ignored "-Wpedantic"
1597#endif
1598#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1599 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1600#endif
1601#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1602 #if defined(__clang__)
1603 #pragma clang diagnostic ignored "-Wvariadic-macros"
1604 #elif defined(JSON_HEDLEY_GCC_VERSION)
1605 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1606 #endif
1607#endif
1608#if defined(JSON_HEDLEY_NON_NULL)
1609 #undef JSON_HEDLEY_NON_NULL
1610#endif
1611#if \
1612 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1613 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1614 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1615 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1616 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1617#else
1618 #define JSON_HEDLEY_NON_NULL(...)
1619#endif
1620JSON_HEDLEY_DIAGNOSTIC_POP
1621
1622#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1623 #undef JSON_HEDLEY_PRINTF_FORMAT
1624#endif
1625#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1626 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1627#elif 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__(gnu_printf, string_idx, first_to_check)))
1629#elif \
1630 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1631 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1632 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1633 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1634 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1635 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1636 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1637 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1638 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1639 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1640 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1641 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1642 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1643 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1644 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1645 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1646 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1647 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1648#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1649 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1650#else
1651 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1652#endif
1653
1654#if defined(JSON_HEDLEY_CONSTEXPR)
1655 #undef JSON_HEDLEY_CONSTEXPR
1656#endif
1657#if defined(__cplusplus)
1658 #if __cplusplus >= 201103L
1659 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1660 #endif
1661#endif
1662#if !defined(JSON_HEDLEY_CONSTEXPR)
1663 #define JSON_HEDLEY_CONSTEXPR
1664#endif
1665
1666#if defined(JSON_HEDLEY_PREDICT)
1667 #undef JSON_HEDLEY_PREDICT
1668#endif
1669#if defined(JSON_HEDLEY_LIKELY)
1670 #undef JSON_HEDLEY_LIKELY
1671#endif
1672#if defined(JSON_HEDLEY_UNLIKELY)
1673 #undef JSON_HEDLEY_UNLIKELY
1674#endif
1675#if defined(JSON_HEDLEY_UNPREDICTABLE)
1676 #undef JSON_HEDLEY_UNPREDICTABLE
1677#endif
1678#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1679 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1680#endif
1681#if \
1682 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1683 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1684 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1685# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1686# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1687# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1688# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1689# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1690#elif \
1691 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1692 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1693 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1694 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1695 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1696 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1697 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1698 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1699 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1700 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1701 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1702 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1703 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1704 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1705 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1706 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1707# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1708 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1709# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1710 (__extension__ ({ \
1711 double hedley_probability_ = (probability); \
1712 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1713 }))
1714# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1715 (__extension__ ({ \
1716 double hedley_probability_ = (probability); \
1717 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1718 }))
1719# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1720# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1721#else
1722# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1723# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1724# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1725# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1726# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1727#endif
1728#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1729 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1730#endif
1731
1732#if defined(JSON_HEDLEY_MALLOC)
1733 #undef JSON_HEDLEY_MALLOC
1734#endif
1735#if \
1736 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1737 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1738 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1739 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1740 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1741 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1742 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1743 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1744 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1745 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1746 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1747 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1748 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1749 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1750 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1751 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1752 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1753 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1754 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1755#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1756 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1757#elif \
1758 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1759 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1760 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1761#else
1762 #define JSON_HEDLEY_MALLOC
1763#endif
1764
1765#if defined(JSON_HEDLEY_PURE)
1766 #undef JSON_HEDLEY_PURE
1767#endif
1768#if \
1769 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1770 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1771 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1772 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1773 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1774 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1775 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1776 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1777 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1778 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1779 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1780 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1782 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1783 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1784 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1785 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1786 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1787 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1788# define JSON_HEDLEY_PURE __attribute__((__pure__))
1789#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1790# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1791#elif defined(__cplusplus) && \
1792 ( \
1793 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1794 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1795 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1796 )
1797# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1798#else
1799# define JSON_HEDLEY_PURE
1800#endif
1801
1802#if defined(JSON_HEDLEY_CONST)
1803 #undef JSON_HEDLEY_CONST
1804#endif
1805#if \
1806 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1807 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1808 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1809 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1810 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1811 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1812 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1813 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1814 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1815 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1816 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1817 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1818 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1819 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1820 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1821 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1822 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1823 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1824 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1825 #define JSON_HEDLEY_CONST __attribute__((__const__))
1826#elif \
1827 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1828 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1829#else
1830 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1831#endif
1832
1833#if defined(JSON_HEDLEY_RESTRICT)
1834 #undef JSON_HEDLEY_RESTRICT
1835#endif
1836#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1837 #define JSON_HEDLEY_RESTRICT restrict
1838#elif \
1839 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1840 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1841 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1842 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1843 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1844 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1845 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1846 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1847 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1848 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1849 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1850 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1851 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1852 defined(__clang__) || \
1853 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1854 #define JSON_HEDLEY_RESTRICT __restrict
1855#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1856 #define JSON_HEDLEY_RESTRICT _Restrict
1857#else
1858 #define JSON_HEDLEY_RESTRICT
1859#endif
1860
1861#if defined(JSON_HEDLEY_INLINE)
1862 #undef JSON_HEDLEY_INLINE
1863#endif
1864#if \
1865 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1866 (defined(__cplusplus) && (__cplusplus >= 199711L))
1867 #define JSON_HEDLEY_INLINE inline
1868#elif \
1869 defined(JSON_HEDLEY_GCC_VERSION) || \
1870 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1871 #define JSON_HEDLEY_INLINE __inline__
1872#elif \
1873 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1874 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1875 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1876 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1877 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1878 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1879 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1880 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1881 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1882 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1883 #define JSON_HEDLEY_INLINE __inline
1884#else
1885 #define JSON_HEDLEY_INLINE
1886#endif
1887
1888#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1889 #undef JSON_HEDLEY_ALWAYS_INLINE
1890#endif
1891#if \
1892 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1893 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1894 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1895 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1896 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1897 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1898 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1899 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1900 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1901 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1902 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1903 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1904 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1905 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1906 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1907 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1908 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1909 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1910 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1911# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1912#elif \
1913 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1914 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1915# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1916#elif defined(__cplusplus) && \
1917 ( \
1918 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1919 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1920 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1921 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1922 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1923 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1924 )
1925# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1926#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1927# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1928#else
1929# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1930#endif
1931
1932#if defined(JSON_HEDLEY_NEVER_INLINE)
1933 #undef JSON_HEDLEY_NEVER_INLINE
1934#endif
1935#if \
1936 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1937 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1938 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1939 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1940 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1941 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1942 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1943 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1944 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1945 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1946 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1947 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1948 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1949 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1950 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1951 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1952 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1953 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1954 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1955 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1956#elif \
1957 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1958 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1959 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1960#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1961 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1962#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1963 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1964#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1965 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1966#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1967 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1968#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1969 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1970#else
1971 #define JSON_HEDLEY_NEVER_INLINE
1972#endif
1973
1974#if defined(JSON_HEDLEY_PRIVATE)
1975 #undef JSON_HEDLEY_PRIVATE
1976#endif
1977#if defined(JSON_HEDLEY_PUBLIC)
1978 #undef JSON_HEDLEY_PUBLIC
1979#endif
1980#if defined(JSON_HEDLEY_IMPORT)
1981 #undef JSON_HEDLEY_IMPORT
1982#endif
1983#if defined(_WIN32) || defined(__CYGWIN__)
1984# define JSON_HEDLEY_PRIVATE
1985# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1986# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1987#else
1988# if \
1989 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1990 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1991 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1992 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1993 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1994 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1995 ( \
1996 defined(__TI_EABI__) && \
1997 ( \
1998 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1999 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2000 ) \
2001 ) || \
2002 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2003# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2004# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2005# else
2006# define JSON_HEDLEY_PRIVATE
2007# define JSON_HEDLEY_PUBLIC
2008# endif
2009# define JSON_HEDLEY_IMPORT extern
2010#endif
2011
2012#if defined(JSON_HEDLEY_NO_THROW)
2013 #undef JSON_HEDLEY_NO_THROW
2014#endif
2015#if \
2016 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2017 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2018 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2019 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2020 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2021#elif \
2022 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2023 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2024 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2025 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2026#else
2027 #define JSON_HEDLEY_NO_THROW
2028#endif
2029
2030#if defined(JSON_HEDLEY_FALL_THROUGH)
2031 #undef JSON_HEDLEY_FALL_THROUGH
2032#endif
2033#if \
2034 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2035 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2036 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2037 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2038#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2039 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2041 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2042#elif defined(__fallthrough) /* SAL */
2043 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2044#else
2045 #define JSON_HEDLEY_FALL_THROUGH
2046#endif
2047
2048#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2049 #undef JSON_HEDLEY_RETURNS_NON_NULL
2050#endif
2051#if \
2052 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2053 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2054 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2055 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2056#elif defined(_Ret_notnull_) /* SAL */
2057 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2058#else
2059 #define JSON_HEDLEY_RETURNS_NON_NULL
2060#endif
2061
2062#if defined(JSON_HEDLEY_ARRAY_PARAM)
2063 #undef JSON_HEDLEY_ARRAY_PARAM
2064#endif
2065#if \
2066 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2067 !defined(__STDC_NO_VLA__) && \
2068 !defined(__cplusplus) && \
2069 !defined(JSON_HEDLEY_PGI_VERSION) && \
2070 !defined(JSON_HEDLEY_TINYC_VERSION)
2071 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2072#else
2073 #define JSON_HEDLEY_ARRAY_PARAM(name)
2074#endif
2075
2076#if defined(JSON_HEDLEY_IS_CONSTANT)
2077 #undef JSON_HEDLEY_IS_CONSTANT
2078#endif
2079#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2080 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2081#endif
2082/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2083 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2084#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2085 #undef JSON_HEDLEY_IS_CONSTEXPR_
2086#endif
2087#if \
2088 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2089 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2090 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2091 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2092 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2094 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2095 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2096 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2097 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2098 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2099#endif
2100#if !defined(__cplusplus)
2101# if \
2102 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2103 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2104 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2105 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2106 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2107 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2108 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2109#if defined(__INTPTR_TYPE__)
2110 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2111#else
2112 #include <stdint.h>
2113 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2114#endif
2115# elif \
2116 ( \
2117 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2118 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2119 !defined(JSON_HEDLEY_PGI_VERSION) && \
2120 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2121 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2122 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2123 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2124 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2125 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2126#if defined(__INTPTR_TYPE__)
2127 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2128#else
2129 #include <stdint.h>
2130 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2131#endif
2132# elif \
2133 defined(JSON_HEDLEY_GCC_VERSION) || \
2134 defined(JSON_HEDLEY_INTEL_VERSION) || \
2135 defined(JSON_HEDLEY_TINYC_VERSION) || \
2136 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2137 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2138 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2139 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2140 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2141 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2142 defined(__clang__)
2143# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2144 sizeof(void) != \
2145 sizeof(*( \
2146 1 ? \
2147 ((void*) ((expr) * 0L) ) : \
2148((struct { char v[sizeof(void) * 2]; } *) 1) \
2149 ) \
2150 ) \
2151 )
2152# endif
2153#endif
2154#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2155 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2156 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2157 #endif
2158 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2159#else
2160 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2161 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2162 #endif
2163 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2164#endif
2165
2166#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2167 #undef JSON_HEDLEY_BEGIN_C_DECLS
2168#endif
2169#if defined(JSON_HEDLEY_END_C_DECLS)
2170 #undef JSON_HEDLEY_END_C_DECLS
2171#endif
2172#if defined(JSON_HEDLEY_C_DECL)
2173 #undef JSON_HEDLEY_C_DECL
2174#endif
2175#if defined(__cplusplus)
2176 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2177 #define JSON_HEDLEY_END_C_DECLS }
2178 #define JSON_HEDLEY_C_DECL extern "C"
2179#else
2180 #define JSON_HEDLEY_BEGIN_C_DECLS
2181 #define JSON_HEDLEY_END_C_DECLS
2182 #define JSON_HEDLEY_C_DECL
2183#endif
2184
2185#if defined(JSON_HEDLEY_STATIC_ASSERT)
2186 #undef JSON_HEDLEY_STATIC_ASSERT
2187#endif
2188#if \
2189 !defined(__cplusplus) && ( \
2190 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2191 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2192 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2193 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2194 defined(_Static_assert) \
2195 )
2196# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2197#elif \
2198 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2199 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2200 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2201# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2202#else
2203# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2204#endif
2205
2206#if defined(JSON_HEDLEY_NULL)
2207 #undef JSON_HEDLEY_NULL
2208#endif
2209#if defined(__cplusplus)
2210 #if __cplusplus >= 201103L
2211 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2212 #elif defined(NULL)
2213 #define JSON_HEDLEY_NULL NULL
2214 #else
2215 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2216 #endif
2217#elif defined(NULL)
2218 #define JSON_HEDLEY_NULL NULL
2219#else
2220 #define JSON_HEDLEY_NULL ((void*) 0)
2221#endif
2222
2223#if defined(JSON_HEDLEY_MESSAGE)
2224 #undef JSON_HEDLEY_MESSAGE
2225#endif
2226#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2227# define JSON_HEDLEY_MESSAGE(msg) \
2228 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2229 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2230 JSON_HEDLEY_PRAGMA(message msg) \
2231 JSON_HEDLEY_DIAGNOSTIC_POP
2232#elif \
2233 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2234 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2235# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2236#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2237# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2238#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2239# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2240#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2241# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2242#else
2243# define JSON_HEDLEY_MESSAGE(msg)
2244#endif
2245
2246#if defined(JSON_HEDLEY_WARNING)
2247 #undef JSON_HEDLEY_WARNING
2248#endif
2249#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2250# define JSON_HEDLEY_WARNING(msg) \
2251 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2252 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2253 JSON_HEDLEY_PRAGMA(clang warning msg) \
2254 JSON_HEDLEY_DIAGNOSTIC_POP
2255#elif \
2256 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2257 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2258 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2259# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2260#elif \
2261 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2262 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2263# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2264#else
2265# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2266#endif
2267
2268#if defined(JSON_HEDLEY_REQUIRE)
2269 #undef JSON_HEDLEY_REQUIRE
2270#endif
2271#if defined(JSON_HEDLEY_REQUIRE_MSG)
2272 #undef JSON_HEDLEY_REQUIRE_MSG
2273#endif
2274#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2275# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2276# define JSON_HEDLEY_REQUIRE(expr) \
2277 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2278 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2279 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2280 JSON_HEDLEY_DIAGNOSTIC_POP
2281# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2282 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2283 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2284 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2285 JSON_HEDLEY_DIAGNOSTIC_POP
2286# else
2287# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2288# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2289# endif
2290#else
2291# define JSON_HEDLEY_REQUIRE(expr)
2292# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2293#endif
2294
2295#if defined(JSON_HEDLEY_FLAGS)
2296 #undef JSON_HEDLEY_FLAGS
2297#endif
2298#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2299 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2300#else
2301 #define JSON_HEDLEY_FLAGS
2302#endif
2303
2304#if defined(JSON_HEDLEY_FLAGS_CAST)
2305 #undef JSON_HEDLEY_FLAGS_CAST
2306#endif
2307#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2308# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2309 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2310 _Pragma("warning(disable:188)") \
2311 ((T) (expr)); \
2312 JSON_HEDLEY_DIAGNOSTIC_POP \
2313 }))
2314#else
2315# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2316#endif
2317
2318#if defined(JSON_HEDLEY_EMPTY_BASES)
2319 #undef JSON_HEDLEY_EMPTY_BASES
2320#endif
2321#if \
2322 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2323 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2324 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2325#else
2326 #define JSON_HEDLEY_EMPTY_BASES
2327#endif
2328
2329/* Remaining macros are deprecated. */
2330
2331#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2332 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2333#endif
2334#if defined(__clang__)
2335 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2336#else
2337 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2338#endif
2339
2340#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2341 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2342#endif
2343#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2344
2345#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2346 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2347#endif
2348#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2349
2350#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2351 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2352#endif
2353#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2354
2355#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2356 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2357#endif
2358#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2359
2360#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2361 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2362#endif
2363#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2364
2365#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2366 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2367#endif
2368#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2369
2370#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2371 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2372#endif
2373#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2374
2375#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2376
2377
2378// This file contains all internal macro definitions (except those affecting ABI)
2379// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2380
2381// #include <nlohmann/detail/abi_macros.hpp>
2382
2383
2384// exclude unsupported compilers
2385#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2386 #if defined(__clang__)
2387 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2388 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2389 #endif
2390 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2391 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2392 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2393 #endif
2394 #endif
2395#endif
2396
2397// C++ language standard detection
2398// if the user manually specified the used C++ version, this is skipped
2399#if !defined(JSON_HAS_CPP_26) && !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)
2400 #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L)
2401 #define JSON_HAS_CPP_26
2402 #define JSON_HAS_CPP_23
2403 #define JSON_HAS_CPP_20
2404 #define JSON_HAS_CPP_17
2405 #define JSON_HAS_CPP_14
2406 #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2407 #define JSON_HAS_CPP_23
2408 #define JSON_HAS_CPP_20
2409 #define JSON_HAS_CPP_17
2410 #define JSON_HAS_CPP_14
2411 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2412 #define JSON_HAS_CPP_20
2413 #define JSON_HAS_CPP_17
2414 #define JSON_HAS_CPP_14
2415 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2416 #define JSON_HAS_CPP_17
2417 #define JSON_HAS_CPP_14
2418 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2419 #define JSON_HAS_CPP_14
2420 #endif
2421 // the cpp 11 flag is always specified because it is the minimal required version
2422 #define JSON_HAS_CPP_11
2423#endif
2424
2425#ifdef __has_include
2426 #if __has_include(<version>)
2427 #include <version>
2428 #endif
2429#endif
2430
2431#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2432 #ifdef JSON_HAS_CPP_17
2433 #if defined(__cpp_lib_filesystem)
2434 #define JSON_HAS_FILESYSTEM 1
2435 #elif defined(__cpp_lib_experimental_filesystem)
2436 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2437 #elif !defined(__has_include)
2438 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2439 #elif __has_include(<filesystem>)
2440 #define JSON_HAS_FILESYSTEM 1
2441 #elif __has_include(<experimental/filesystem>)
2442 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2443 #endif
2444
2445 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2446 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2447 #undef JSON_HAS_FILESYSTEM
2448 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2449 #endif
2450
2451 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2452 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2453 #undef JSON_HAS_FILESYSTEM
2454 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2455 #endif
2456
2457 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2458 #if defined(__clang_major__) && __clang_major__ < 7
2459 #undef JSON_HAS_FILESYSTEM
2460 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461 #endif
2462
2463 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2464 #if defined(_MSC_VER) && _MSC_VER < 1914
2465 #undef JSON_HAS_FILESYSTEM
2466 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2467 #endif
2468
2469 // no filesystem support before iOS 13
2470 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2471 #undef JSON_HAS_FILESYSTEM
2472 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2473 #endif
2474
2475 // no filesystem support before macOS Catalina
2476 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2477 #undef JSON_HAS_FILESYSTEM
2478 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2479 #endif
2480 #endif
2481#endif
2482
2483#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2484 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2485#endif
2486
2487#ifndef JSON_HAS_FILESYSTEM
2488 #define JSON_HAS_FILESYSTEM 0
2489#endif
2490
2491#ifndef JSON_HAS_THREE_WAY_COMPARISON
2492 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2493 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2494 #define JSON_HAS_THREE_WAY_COMPARISON 1
2495 #else
2496 #define JSON_HAS_THREE_WAY_COMPARISON 0
2497 #endif
2498#endif
2499
2500#ifndef JSON_HAS_RANGES
2501 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2502 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2503 #define JSON_HAS_RANGES 0
2504 #elif defined(__cpp_lib_ranges)
2505 #define JSON_HAS_RANGES 1
2506 #else
2507 #define JSON_HAS_RANGES 0
2508 #endif
2509#endif
2510
2511#ifndef JSON_HAS_STATIC_RTTI
2512 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2513 #define JSON_HAS_STATIC_RTTI 1
2514 #else
2515 #define JSON_HAS_STATIC_RTTI 0
2516 #endif
2517#endif
2518
2519#ifdef JSON_HAS_CPP_17
2520 #define JSON_INLINE_VARIABLE inline
2521#else
2522 #define JSON_INLINE_VARIABLE
2523#endif
2524
2525#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2526 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2527#else
2528 #define JSON_NO_UNIQUE_ADDRESS
2529#endif
2530
2531// disable documentation warnings on clang
2532#if defined(__clang__)
2533 #pragma clang diagnostic push
2534 #pragma clang diagnostic ignored "-Wdocumentation"
2535 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2536#endif
2537
2538// allow disabling exceptions
2539#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2540 #define JSON_THROW(exception) throw exception
2541 #define JSON_TRY try
2542 #define JSON_CATCH(exception) catch(exception)
2543 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2544#else
2545 #include <cstdlib>
2546 #define JSON_THROW(exception) std::abort()
2547 #define JSON_TRY if(true)
2548 #define JSON_CATCH(exception) if(false)
2549 #define JSON_INTERNAL_CATCH(exception) if(false)
2550#endif
2551
2552// override exception macros
2553#if defined(JSON_THROW_USER)
2554 #undef JSON_THROW
2555 #define JSON_THROW JSON_THROW_USER
2556#endif
2557#if defined(JSON_TRY_USER)
2558 #undef JSON_TRY
2559 #define JSON_TRY JSON_TRY_USER
2560#endif
2561#if defined(JSON_CATCH_USER)
2562 #undef JSON_CATCH
2563 #define JSON_CATCH JSON_CATCH_USER
2564 #undef JSON_INTERNAL_CATCH
2565 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2566#endif
2567#if defined(JSON_INTERNAL_CATCH_USER)
2568 #undef JSON_INTERNAL_CATCH
2569 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2570#endif
2571
2572// allow overriding assert
2573#if !defined(JSON_ASSERT)
2574 #include <cassert> // assert
2575 #define JSON_ASSERT(x) assert(x)
2576#endif
2577
2578// allow accessing some private functions (needed by the test suite)
2579#if defined(JSON_TESTS_PRIVATE)
2580 #define JSON_PRIVATE_UNLESS_TESTED public
2581#else
2582 #define JSON_PRIVATE_UNLESS_TESTED private
2583#endif
2584
2590#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2591 template<typename BasicJsonType> \
2592 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2593 { \
2594 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2595 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2596 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2597 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2598 auto it = std::find_if(std::begin(m), std::end(m), \
2599 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2600 { \
2601 return ej_pair.first == e; \
2602 }); \
2603 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2604 } \
2605 template<typename BasicJsonType> \
2606 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2607 { \
2608 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2609 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2610 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2611 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2612 auto it = std::find_if(std::begin(m), std::end(m), \
2613 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2614 { \
2615 return ej_pair.second == j; \
2616 }); \
2617 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2618 }
2619
2620// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2621// may be removed in the future once the class is split.
2622
2623#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2624 template<template<typename, typename, typename...> class ObjectType, \
2625 template<typename, typename...> class ArrayType, \
2626 class StringType, class BooleanType, class NumberIntegerType, \
2627 class NumberUnsignedType, class NumberFloatType, \
2628 template<typename> class AllocatorType, \
2629 template<typename, typename = void> class JSONSerializer, \
2630 class BinaryType, \
2631 class CustomBaseClass>
2632
2633#define NLOHMANN_BASIC_JSON_TPL \
2634 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2635 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2636 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2637
2638// Macros to simplify conversion from/to types
2639
2640#define NLOHMANN_JSON_EXPAND( x ) x
2641#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
2642#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2643 NLOHMANN_JSON_PASTE64, \
2644 NLOHMANN_JSON_PASTE63, \
2645 NLOHMANN_JSON_PASTE62, \
2646 NLOHMANN_JSON_PASTE61, \
2647 NLOHMANN_JSON_PASTE60, \
2648 NLOHMANN_JSON_PASTE59, \
2649 NLOHMANN_JSON_PASTE58, \
2650 NLOHMANN_JSON_PASTE57, \
2651 NLOHMANN_JSON_PASTE56, \
2652 NLOHMANN_JSON_PASTE55, \
2653 NLOHMANN_JSON_PASTE54, \
2654 NLOHMANN_JSON_PASTE53, \
2655 NLOHMANN_JSON_PASTE52, \
2656 NLOHMANN_JSON_PASTE51, \
2657 NLOHMANN_JSON_PASTE50, \
2658 NLOHMANN_JSON_PASTE49, \
2659 NLOHMANN_JSON_PASTE48, \
2660 NLOHMANN_JSON_PASTE47, \
2661 NLOHMANN_JSON_PASTE46, \
2662 NLOHMANN_JSON_PASTE45, \
2663 NLOHMANN_JSON_PASTE44, \
2664 NLOHMANN_JSON_PASTE43, \
2665 NLOHMANN_JSON_PASTE42, \
2666 NLOHMANN_JSON_PASTE41, \
2667 NLOHMANN_JSON_PASTE40, \
2668 NLOHMANN_JSON_PASTE39, \
2669 NLOHMANN_JSON_PASTE38, \
2670 NLOHMANN_JSON_PASTE37, \
2671 NLOHMANN_JSON_PASTE36, \
2672 NLOHMANN_JSON_PASTE35, \
2673 NLOHMANN_JSON_PASTE34, \
2674 NLOHMANN_JSON_PASTE33, \
2675 NLOHMANN_JSON_PASTE32, \
2676 NLOHMANN_JSON_PASTE31, \
2677 NLOHMANN_JSON_PASTE30, \
2678 NLOHMANN_JSON_PASTE29, \
2679 NLOHMANN_JSON_PASTE28, \
2680 NLOHMANN_JSON_PASTE27, \
2681 NLOHMANN_JSON_PASTE26, \
2682 NLOHMANN_JSON_PASTE25, \
2683 NLOHMANN_JSON_PASTE24, \
2684 NLOHMANN_JSON_PASTE23, \
2685 NLOHMANN_JSON_PASTE22, \
2686 NLOHMANN_JSON_PASTE21, \
2687 NLOHMANN_JSON_PASTE20, \
2688 NLOHMANN_JSON_PASTE19, \
2689 NLOHMANN_JSON_PASTE18, \
2690 NLOHMANN_JSON_PASTE17, \
2691 NLOHMANN_JSON_PASTE16, \
2692 NLOHMANN_JSON_PASTE15, \
2693 NLOHMANN_JSON_PASTE14, \
2694 NLOHMANN_JSON_PASTE13, \
2695 NLOHMANN_JSON_PASTE12, \
2696 NLOHMANN_JSON_PASTE11, \
2697 NLOHMANN_JSON_PASTE10, \
2698 NLOHMANN_JSON_PASTE9, \
2699 NLOHMANN_JSON_PASTE8, \
2700 NLOHMANN_JSON_PASTE7, \
2701 NLOHMANN_JSON_PASTE6, \
2702 NLOHMANN_JSON_PASTE5, \
2703 NLOHMANN_JSON_PASTE4, \
2704 NLOHMANN_JSON_PASTE3, \
2705 NLOHMANN_JSON_PASTE2, \
2706 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2707#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2708#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2709#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2710#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2711#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757#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)
2758#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)
2759#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)
2760#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)
2761#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)
2762#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)
2763#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)
2764#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)
2765#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)
2766#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)
2767#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)
2768#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)
2769#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)
2770
2771#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2772#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2773#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;
2774
2781#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2782 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2783 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2784 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2785 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2786
2793#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2794 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2795 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2796 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2797 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__)) }
2798
2805#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2806 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2807 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2808
2815#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2816 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2817 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2818 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2819 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2820
2827#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2828 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2829 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2830 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2831 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__)) }
2832
2839#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2840 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2841 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2842
2849#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2850 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2851 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__)) } \
2852 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2853 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__)) }
2854
2861#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2862 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2863 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__)) } \
2864 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2865 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__)) }
2866
2873#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2874 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2875 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__)) }
2876
2883#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2884 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2885 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__)) } \
2886 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2887 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__)) }
2888
2895#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2896 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2897 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__)) } \
2898 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2899 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__)) }
2900
2907#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2908 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2909 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__)) }
2910
2911// inspired from https://stackoverflow.com/a/26745591
2912// allows calling any std function as if (e.g., with begin):
2913// using std::begin; begin(x);
2914//
2915// it allows using the detected idiom to retrieve the return type
2916// of such an expression
2917#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2918 namespace detail { \
2919 using std::std_name; \
2920 \
2921 template<typename... T> \
2922 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2923 } \
2924 \
2925 namespace detail2 { \
2926 struct std_name##_tag \
2927 { \
2928 }; \
2929 \
2930 template<typename... T> \
2931 std_name##_tag std_name(T&&...); \
2932 \
2933 template<typename... T> \
2934 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2935 \
2936 template<typename... T> \
2937 struct would_call_std_##std_name \
2938 { \
2939 static constexpr auto const value = ::nlohmann::detail:: \
2940 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2941 }; \
2942 } /* namespace detail2 */ \
2943 \
2944 template<typename... T> \
2945 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2946 { \
2947 }
2948
2949#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2950 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2951#endif
2952
2953#if JSON_USE_IMPLICIT_CONVERSIONS
2954 #define JSON_EXPLICIT
2955#else
2956 #define JSON_EXPLICIT explicit
2957#endif
2958
2959#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2960 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2961#endif
2962
2963#ifndef JSON_USE_GLOBAL_UDLS
2964 #define JSON_USE_GLOBAL_UDLS 1
2965#endif
2966
2967#if JSON_HAS_THREE_WAY_COMPARISON
2968 #include <compare> // partial_ordering
2969#endif
2970
2971NLOHMANN_JSON_NAMESPACE_BEGIN
2972namespace detail
2973{
2974
2976// JSON type enumeration //
2978
3016
3030#if JSON_HAS_THREE_WAY_COMPARISON
3031 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3032#else
3033 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3034#endif
3035{
3036 static constexpr std::array<std::uint8_t, 9> order = {{
3037 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3038 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3039 6 /* binary */
3040 }
3041 };
3042
3043 const auto l_index = static_cast<std::size_t>(lhs);
3044 const auto r_index = static_cast<std::size_t>(rhs);
3045#if JSON_HAS_THREE_WAY_COMPARISON
3046 if (l_index < order.size() && r_index < order.size())
3047 {
3048 return order[l_index] <=> order[r_index]; // *NOPAD*
3049 }
3050 return std::partial_ordering::unordered;
3051#else
3052 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3053#endif
3054}
3055
3056// GCC selects the built-in operator< over an operator rewritten from
3057// a user-defined spaceship operator
3058// Clang, MSVC, and ICC select the rewritten candidate
3059// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3060#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3061inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3062{
3063 return std::is_lt(lhs <=> rhs); // *NOPAD*
3064}
3065#endif
3066
3067} // namespace detail
3068NLOHMANN_JSON_NAMESPACE_END
3069
3070// #include <nlohmann/detail/string_escape.hpp>
3071// __ _____ _____ _____
3072// __| | __| | | | JSON for Modern C++
3073// | | |__ | | | | | | version 3.12.0
3074// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3075//
3076// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3077// SPDX-License-Identifier: MIT
3078
3079
3080
3081// #include <nlohmann/detail/abi_macros.hpp>
3082
3083
3084NLOHMANN_JSON_NAMESPACE_BEGIN
3085namespace detail
3086{
3087
3101template<typename StringType>
3102inline void replace_substring(StringType& s, const StringType& f,
3103 const StringType& t)
3104{
3105 JSON_ASSERT(!f.empty());
3106 for (auto pos = s.find(f); // find the first occurrence of f
3107 pos != StringType::npos; // make sure f was found
3108 s.replace(pos, f.size(), t), // replace with t, and
3109 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3110 {}
3111}
3112
3120template<typename StringType>
3121inline StringType escape(StringType s)
3122{
3123 replace_substring(s, StringType{"~"}, StringType{"~0"});
3124 replace_substring(s, StringType{"/"}, StringType{"~1"});
3125 return s;
3126}
3127
3135template<typename StringType>
3136inline void unescape(StringType& s)
3137{
3138 replace_substring(s, StringType{"~1"}, StringType{"/"});
3139 replace_substring(s, StringType{"~0"}, StringType{"~"});
3140}
3141
3142} // namespace detail
3143NLOHMANN_JSON_NAMESPACE_END
3144
3145// #include <nlohmann/detail/input/position_t.hpp>
3146// __ _____ _____ _____
3147// __| | __| | | | JSON for Modern C++
3148// | | |__ | | | | | | version 3.12.0
3149// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3150//
3151// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3152// SPDX-License-Identifier: MIT
3153
3154
3155
3156#include <cstddef> // size_t
3157
3158// #include <nlohmann/detail/abi_macros.hpp>
3159
3160
3161NLOHMANN_JSON_NAMESPACE_BEGIN
3162namespace detail
3163{
3164
3167{
3169 std::size_t chars_read_total = 0;
3173 std::size_t lines_read = 0;
3174
3176 constexpr operator size_t() const
3177 {
3178 return chars_read_total;
3179 }
3180};
3181
3182} // namespace detail
3183NLOHMANN_JSON_NAMESPACE_END
3184
3185// #include <nlohmann/detail/macro_scope.hpp>
3186
3187// #include <nlohmann/detail/meta/cpp_future.hpp>
3188// __ _____ _____ _____
3189// __| | __| | | | JSON for Modern C++
3190// | | |__ | | | | | | version 3.12.0
3191// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3192//
3193// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3194// SPDX-FileCopyrightText: 2018 The Abseil Authors
3195// SPDX-License-Identifier: MIT
3196
3197
3198
3199#include <array> // array
3200#include <cstddef> // size_t
3201#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3202#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3203
3204// #include <nlohmann/detail/macro_scope.hpp>
3205
3206
3207NLOHMANN_JSON_NAMESPACE_BEGIN
3208namespace detail
3209{
3210
3211template<typename T>
3212using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3213
3214#ifdef JSON_HAS_CPP_14
3215
3216// the following utilities are natively available in C++14
3217using std::enable_if_t;
3218using std::index_sequence;
3219using std::make_index_sequence;
3220using std::index_sequence_for;
3221
3222#else
3223
3224// alias templates to reduce boilerplate
3225template<bool B, typename T = void>
3226using enable_if_t = typename std::enable_if<B, T>::type;
3227
3228// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3229// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3230
3232
3233// integer_sequence
3234//
3235// Class template representing a compile-time integer sequence. An instantiation
3236// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3237// type through its template arguments (which is a common need when
3238// working with C++11 variadic templates). `absl::integer_sequence` is designed
3239// to be a drop-in replacement for C++14's `std::integer_sequence`.
3240//
3241// Example:
3242//
3243// template< class T, T... Ints >
3244// void user_function(integer_sequence<T, Ints...>);
3245//
3246// int main()
3247// {
3248// // user_function's `T` will be deduced to `int` and `Ints...`
3249// // will be deduced to `0, 1, 2, 3, 4`.
3250// user_function(make_integer_sequence<int, 5>());
3251// }
3252template <typename T, T... Ints>
3254{
3255 using value_type = T;
3256 static constexpr std::size_t size() noexcept
3257 {
3258 return sizeof...(Ints);
3259 }
3260};
3261
3262// index_sequence
3263//
3264// A helper template for an `integer_sequence` of `size_t`,
3265// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3266// `std::index_sequence`.
3267template <size_t... Ints>
3268using index_sequence = integer_sequence<size_t, Ints...>;
3269
3270namespace utility_internal
3271{
3272
3273template <typename Seq, size_t SeqSize, size_t Rem>
3274struct Extend;
3275
3276// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3277template <typename T, T... Ints, size_t SeqSize>
3278struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3279{
3280 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3281};
3282
3283template <typename T, T... Ints, size_t SeqSize>
3284struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3285{
3286 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3287};
3288
3289// Recursion helper for 'make_integer_sequence<T, N>'.
3290// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3291template <typename T, size_t N>
3292struct Gen
3293{
3294 using type =
3295 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3296};
3297
3298template <typename T>
3299struct Gen<T, 0>
3300{
3301 using type = integer_sequence<T>;
3302};
3303
3304} // namespace utility_internal
3305
3306// Compile-time sequences of integers
3307
3308// make_integer_sequence
3309//
3310// This template alias is equivalent to
3311// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3312// replacement for C++14's `std::make_integer_sequence`.
3313template <typename T, T N>
3314using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3315
3316// make_index_sequence
3317//
3318// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3319// and is designed to be a drop-in replacement for C++14's
3320// `std::make_index_sequence`.
3321template <size_t N>
3322using make_index_sequence = make_integer_sequence<size_t, N>;
3323
3324// index_sequence_for
3325//
3326// Converts a typename pack into an index sequence of the same length, and
3327// is designed to be a drop-in replacement for C++14's
3328// `std::index_sequence_for()`
3329template <typename... Ts>
3330using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3331
3333
3334#endif
3335
3336// dispatch utility (taken from ranges-v3)
3337template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3338template<> struct priority_tag<0> {};
3339
3340// taken from ranges-v3
3341template<typename T>
3343{
3344 static JSON_INLINE_VARIABLE constexpr T value{};
3345};
3346
3347#ifndef JSON_HAS_CPP_17
3348 template<typename T>
3349 constexpr T static_const<T>::value;
3350#endif
3351
3352template<typename T, typename... Args>
3353constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3354{
3355 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3356}
3357
3358} // namespace detail
3359NLOHMANN_JSON_NAMESPACE_END
3360
3361// #include <nlohmann/detail/meta/type_traits.hpp>
3362// __ _____ _____ _____
3363// __| | __| | | | JSON for Modern C++
3364// | | |__ | | | | | | version 3.12.0
3365// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3366//
3367// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3368// SPDX-License-Identifier: MIT
3369
3370
3371
3372#include <limits> // numeric_limits
3373#include <string> // char_traits
3374#include <tuple> // tuple
3375#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3376#include <utility> // declval
3377#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3378 #include <cstddef> // byte
3379#endif
3380// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3381// __ _____ _____ _____
3382// __| | __| | | | JSON for Modern C++
3383// | | |__ | | | | | | version 3.12.0
3384// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3385//
3386// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3387// SPDX-License-Identifier: MIT
3388
3389
3390
3391#include <iterator> // random_access_iterator_tag
3392
3393// #include <nlohmann/detail/abi_macros.hpp>
3394
3395// #include <nlohmann/detail/meta/void_t.hpp>
3396
3397// #include <nlohmann/detail/meta/cpp_future.hpp>
3398
3399
3400NLOHMANN_JSON_NAMESPACE_BEGIN
3401namespace detail
3402{
3403
3404template<typename It, typename = void>
3406
3407template<typename It>
3409 It,
3410 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3411 typename It::reference, typename It::iterator_category >>
3412{
3413 using difference_type = typename It::difference_type;
3414 using value_type = typename It::value_type;
3415 using pointer = typename It::pointer;
3416 using reference = typename It::reference;
3417 using iterator_category = typename It::iterator_category;
3418};
3419
3420// This is required as some compilers implement std::iterator_traits in a way that
3421// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3422template<typename T, typename = void>
3424{
3425};
3426
3427template<typename T>
3428struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3429 : iterator_types<T>
3430{
3431};
3432
3433template<typename T>
3434struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3435{
3436 using iterator_category = std::random_access_iterator_tag;
3437 using value_type = T;
3438 using difference_type = ptrdiff_t;
3439 using pointer = T*;
3440 using reference = T&;
3441};
3442
3443} // namespace detail
3444NLOHMANN_JSON_NAMESPACE_END
3445
3446// #include <nlohmann/detail/macro_scope.hpp>
3447
3448// #include <nlohmann/detail/meta/call_std/begin.hpp>
3449// __ _____ _____ _____
3450// __| | __| | | | JSON for Modern C++
3451// | | |__ | | | | | | version 3.12.0
3452// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3453//
3454// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3455// SPDX-License-Identifier: MIT
3456
3457
3458
3459// #include <nlohmann/detail/macro_scope.hpp>
3460
3461
3462NLOHMANN_JSON_NAMESPACE_BEGIN
3463
3464NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3465
3466NLOHMANN_JSON_NAMESPACE_END
3467
3468// #include <nlohmann/detail/meta/call_std/end.hpp>
3469// __ _____ _____ _____
3470// __| | __| | | | JSON for Modern C++
3471// | | |__ | | | | | | version 3.12.0
3472// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3473//
3474// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3475// SPDX-License-Identifier: MIT
3476
3477
3478
3479// #include <nlohmann/detail/macro_scope.hpp>
3480
3481
3482NLOHMANN_JSON_NAMESPACE_BEGIN
3483
3484NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3485
3486NLOHMANN_JSON_NAMESPACE_END
3487
3488// #include <nlohmann/detail/meta/cpp_future.hpp>
3489
3490// #include <nlohmann/detail/meta/detected.hpp>
3491
3492// #include <nlohmann/json_fwd.hpp>
3493// __ _____ _____ _____
3494// __| | __| | | | JSON for Modern C++
3495// | | |__ | | | | | | version 3.12.0
3496// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3497//
3498// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
3499// SPDX-License-Identifier: MIT
3500
3501#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3502 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3503
3504 #include <cstdint> // int64_t, uint64_t
3505 #include <map> // map
3506 #include <memory> // allocator
3507 #include <string> // string
3508 #include <vector> // vector
3509
3510 // #include <nlohmann/detail/abi_macros.hpp>
3511
3512
3518 NLOHMANN_JSON_NAMESPACE_BEGIN
3519
3527 template<typename T = void, typename SFINAE = void>
3528 struct adl_serializer;
3529
3532 template<template<typename U, typename V, typename... Args> class ObjectType =
3533 std::map,
3534 template<typename U, typename... Args> class ArrayType = std::vector,
3535 class StringType = std::string, class BooleanType = bool,
3536 class NumberIntegerType = std::int64_t,
3537 class NumberUnsignedType = std::uint64_t,
3538 class NumberFloatType = double,
3539 template<typename U> class AllocatorType = std::allocator,
3540 template<typename T, typename SFINAE = void> class JSONSerializer =
3542 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3543 class CustomBaseClass = void>
3544 class basic_json;
3545
3548 template<typename RefStringType>
3549 class json_pointer;
3550
3555 using json = basic_json<>;
3556
3559 template<class Key, class T, class IgnoredLess, class Allocator>
3560 struct ordered_map;
3561
3564 using ordered_json = basic_json<nlohmann::ordered_map>;
3565
3566 NLOHMANN_JSON_NAMESPACE_END
3567
3568#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3569
3570
3571NLOHMANN_JSON_NAMESPACE_BEGIN
3580namespace detail
3581{
3582
3584// helpers //
3586
3587// Note to maintainers:
3588//
3589// Every trait in this file expects a non-CV-qualified type.
3590// The only exceptions are in the 'aliases for detected' section
3591// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3592//
3593// In this case, T has to be properly CV-qualified to constraint the function arguments
3594// (e.g., to_json(BasicJsonType&, const T&))
3595
3596template<typename> struct is_basic_json : std::false_type {};
3597
3598NLOHMANN_BASIC_JSON_TPL_DECLARATION
3599struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3600
3601// used by exceptions create() member functions
3602// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3603// false_type otherwise
3604template<typename BasicJsonContext>
3606 std::integral_constant < bool,
3607 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3608 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3609{};
3610
3612// json_ref helpers //
3614
3615template<typename>
3616class json_ref;
3617
3618template<typename>
3619struct is_json_ref : std::false_type {};
3620
3621template<typename T>
3622struct is_json_ref<json_ref<T>> : std::true_type {};
3623
3625// aliases for detected //
3627
3628template<typename T>
3629using mapped_type_t = typename T::mapped_type;
3630
3631template<typename T>
3632using key_type_t = typename T::key_type;
3633
3634template<typename T>
3635using value_type_t = typename T::value_type;
3636
3637template<typename T>
3638using difference_type_t = typename T::difference_type;
3639
3640template<typename T>
3641using pointer_t = typename T::pointer;
3642
3643template<typename T>
3644using reference_t = typename T::reference;
3645
3646template<typename T>
3647using iterator_category_t = typename T::iterator_category;
3648
3649template<typename T, typename... Args>
3650using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3651
3652template<typename T, typename... Args>
3653using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3654
3655template<typename T, typename U>
3656using get_template_function = decltype(std::declval<T>().template get<U>());
3657
3658// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3659template<typename BasicJsonType, typename T, typename = void>
3660struct has_from_json : std::false_type {};
3661
3662// trait checking if j.get<T> is valid
3663// use this trait instead of std::is_constructible or std::is_convertible,
3664// both rely on, or make use of implicit conversions, and thus fail when T
3665// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3666template <typename BasicJsonType, typename T>
3668{
3669 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3670};
3671
3672template<typename BasicJsonType, typename T>
3673struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3674{
3675 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3676
3677 static constexpr bool value =
3678 is_detected_exact<void, from_json_function, serializer,
3679 const BasicJsonType&, T&>::value;
3680};
3681
3682// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3683// this overload is used for non-default-constructible user-defined-types
3684template<typename BasicJsonType, typename T, typename = void>
3685struct has_non_default_from_json : std::false_type {};
3686
3687template<typename BasicJsonType, typename T>
3688struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3689{
3690 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3691
3692 static constexpr bool value =
3693 is_detected_exact<T, from_json_function, serializer,
3694 const BasicJsonType&>::value;
3695};
3696
3697// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3698// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3699template<typename BasicJsonType, typename T, typename = void>
3700struct has_to_json : std::false_type {};
3701
3702template<typename BasicJsonType, typename T>
3703struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3704{
3705 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3706
3707 static constexpr bool value =
3708 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3709 T>::value;
3710};
3711
3712template<typename T>
3713using detect_key_compare = typename T::key_compare;
3714
3715template<typename T>
3716struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3717
3718// obtains the actual object key comparator
3719template<typename BasicJsonType>
3721{
3722 using object_t = typename BasicJsonType::object_t;
3723 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3724 using type = typename std::conditional < has_key_compare<object_t>::value,
3725 typename object_t::key_compare, object_comparator_t>::type;
3726};
3727
3728template<typename BasicJsonType>
3729using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3730
3732// char_traits //
3734
3735// Primary template of char_traits calls std char_traits
3736template<typename T>
3737struct char_traits : std::char_traits<T>
3738{};
3739
3740// Explicitly define char traits for unsigned char since it is not standard
3741template<>
3742struct char_traits<unsigned char> : std::char_traits<char>
3743{
3744 using char_type = unsigned char;
3745 using int_type = uint64_t;
3746
3747 // Redefine to_int_type function
3748 static int_type to_int_type(char_type c) noexcept
3749 {
3750 return static_cast<int_type>(c);
3751 }
3752
3753 static char_type to_char_type(int_type i) noexcept
3754 {
3755 return static_cast<char_type>(i);
3756 }
3757
3758 static constexpr int_type eof() noexcept
3759 {
3760 return static_cast<int_type>(std::char_traits<char>::eof());
3761 }
3762};
3763
3764// Explicitly define char traits for signed char since it is not standard
3765template<>
3766struct char_traits<signed char> : std::char_traits<char>
3767{
3768 using char_type = signed char;
3769 using int_type = uint64_t;
3770
3771 // Redefine to_int_type function
3772 static int_type to_int_type(char_type c) noexcept
3773 {
3774 return static_cast<int_type>(c);
3775 }
3776
3777 static char_type to_char_type(int_type i) noexcept
3778 {
3779 return static_cast<char_type>(i);
3780 }
3781
3782 static constexpr int_type eof() noexcept
3783 {
3784 return static_cast<int_type>(std::char_traits<char>::eof());
3785 }
3786};
3787
3788#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3789template<>
3790struct char_traits<std::byte> : std::char_traits<char>
3791{
3792 using char_type = std::byte;
3793 using int_type = uint64_t;
3794
3795 static int_type to_int_type(char_type c) noexcept
3796 {
3797 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3798 }
3799
3800 static char_type to_char_type(int_type i) noexcept
3801 {
3802 return std::byte(static_cast<unsigned char>(i));
3803 }
3804
3805 static constexpr int_type eof() noexcept
3806 {
3807 return static_cast<int_type>(std::char_traits<char>::eof());
3808 }
3809};
3810#endif
3811
3813// is_ functions //
3815
3816// https://en.cppreference.com/w/cpp/types/conjunction
3817template<class...> struct conjunction : std::true_type { };
3818template<class B> struct conjunction<B> : B { };
3819template<class B, class... Bn>
3820struct conjunction<B, Bn...>
3821: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3822
3823// https://en.cppreference.com/w/cpp/types/negation
3824template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3825
3826// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3827// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3828// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3829template <typename T>
3830struct is_default_constructible : std::is_default_constructible<T> {};
3831
3832template <typename T1, typename T2>
3833struct is_default_constructible<std::pair<T1, T2>>
3834 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3835
3836template <typename T1, typename T2>
3837struct is_default_constructible<const std::pair<T1, T2>>
3838 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3839
3840template <typename... Ts>
3841struct is_default_constructible<std::tuple<Ts...>>
3842 : conjunction<is_default_constructible<Ts>...> {};
3843
3844template <typename... Ts>
3845struct is_default_constructible<const std::tuple<Ts...>>
3846 : conjunction<is_default_constructible<Ts>...> {};
3847
3848template <typename T, typename... Args>
3849struct is_constructible : std::is_constructible<T, Args...> {};
3850
3851template <typename T1, typename T2>
3852struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3853
3854template <typename T1, typename T2>
3855struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3856
3857template <typename... Ts>
3858struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3859
3860template <typename... Ts>
3861struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3862
3863template<typename T, typename = void>
3864struct is_iterator_traits : std::false_type {};
3865
3866template<typename T>
3868{
3869 private:
3870 using traits = iterator_traits<T>;
3871
3872 public:
3873 static constexpr auto value =
3874 is_detected<value_type_t, traits>::value &&
3875 is_detected<difference_type_t, traits>::value &&
3876 is_detected<pointer_t, traits>::value &&
3877 is_detected<iterator_category_t, traits>::value &&
3878 is_detected<reference_t, traits>::value;
3879};
3880
3881template<typename T>
3883{
3884 private:
3885 using t_ref = typename std::add_lvalue_reference<T>::type;
3886
3887 using iterator = detected_t<result_of_begin, t_ref>;
3888 using sentinel = detected_t<result_of_end, t_ref>;
3889
3890 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3891 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3892 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3893 static constexpr auto is_iterator_begin =
3895
3896 public:
3897 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3898};
3899
3900template<typename R>
3901using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3902
3903template<typename T>
3904using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3905
3906// The following implementation of is_complete_type is taken from
3907// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3908// and is written by Xiang Fan who agreed to use it in this library.
3909
3910template<typename T, typename = void>
3911struct is_complete_type : std::false_type {};
3912
3913template<typename T>
3914struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3915
3916template<typename BasicJsonType, typename CompatibleObjectType,
3917 typename = void>
3918struct is_compatible_object_type_impl : std::false_type {};
3919
3920template<typename BasicJsonType, typename CompatibleObjectType>
3922 BasicJsonType, CompatibleObjectType,
3923 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3924 is_detected<key_type_t, CompatibleObjectType>::value >>
3925{
3926 using object_t = typename BasicJsonType::object_t;
3927
3928 // macOS's is_constructible does not play well with nonesuch...
3929 static constexpr bool value =
3930 is_constructible<typename object_t::key_type,
3931 typename CompatibleObjectType::key_type>::value &&
3932 is_constructible<typename object_t::mapped_type,
3933 typename CompatibleObjectType::mapped_type>::value;
3934};
3935
3936template<typename BasicJsonType, typename CompatibleObjectType>
3938 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3939
3940template<typename BasicJsonType, typename ConstructibleObjectType,
3941 typename = void>
3942struct is_constructible_object_type_impl : std::false_type {};
3943
3944template<typename BasicJsonType, typename ConstructibleObjectType>
3946 BasicJsonType, ConstructibleObjectType,
3947 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3948 is_detected<key_type_t, ConstructibleObjectType>::value >>
3949{
3950 using object_t = typename BasicJsonType::object_t;
3951
3952 static constexpr bool value =
3954 (std::is_move_assignable<ConstructibleObjectType>::value ||
3955 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3956 (is_constructible<typename ConstructibleObjectType::key_type,
3957 typename object_t::key_type>::value &&
3958 std::is_same <
3959 typename object_t::mapped_type,
3960 typename ConstructibleObjectType::mapped_type >::value)) ||
3961 (has_from_json<BasicJsonType,
3962 typename ConstructibleObjectType::mapped_type>::value ||
3964 BasicJsonType,
3965 typename ConstructibleObjectType::mapped_type >::value);
3966};
3967
3968template<typename BasicJsonType, typename ConstructibleObjectType>
3970 : is_constructible_object_type_impl<BasicJsonType,
3971 ConstructibleObjectType> {};
3972
3973template<typename BasicJsonType, typename CompatibleStringType>
3979
3980template<typename BasicJsonType, typename ConstructibleStringType>
3982{
3983 // launder type through decltype() to fix compilation failure on ICPC
3984#ifdef __INTEL_COMPILER
3985 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3986#else
3987 using laundered_type = ConstructibleStringType;
3988#endif
3989
3990 static constexpr auto value =
3991 conjunction <
3993 is_detected_exact<typename BasicJsonType::string_t::value_type,
3994 value_type_t, laundered_type >>::value;
3995};
3996
3997template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3998struct is_compatible_array_type_impl : std::false_type {};
3999
4000template<typename BasicJsonType, typename CompatibleArrayType>
4002 BasicJsonType, CompatibleArrayType,
4003 enable_if_t <
4004 is_detected<iterator_t, CompatibleArrayType>::value&&
4005 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
4006// special case for types like std::filesystem::path whose iterator's value_type are themselves
4007// c.f. https://github.com/nlohmann/json/pull/3073
4008 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4009{
4010 static constexpr bool value =
4011 is_constructible<BasicJsonType,
4012 range_value_t<CompatibleArrayType>>::value;
4013};
4014
4015template<typename BasicJsonType, typename CompatibleArrayType>
4017 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4018
4019template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4020struct is_constructible_array_type_impl : std::false_type {};
4021
4022template<typename BasicJsonType, typename ConstructibleArrayType>
4024 BasicJsonType, ConstructibleArrayType,
4025 enable_if_t<std::is_same<ConstructibleArrayType,
4026 typename BasicJsonType::value_type>::value >>
4027 : std::true_type {};
4028
4029template<typename BasicJsonType, typename ConstructibleArrayType>
4031 BasicJsonType, ConstructibleArrayType,
4032 enable_if_t < !std::is_same<ConstructibleArrayType,
4033 typename BasicJsonType::value_type>::value&&
4034 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4035 is_default_constructible<ConstructibleArrayType>::value&&
4036(std::is_move_assignable<ConstructibleArrayType>::value ||
4037 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4038is_detected<iterator_t, ConstructibleArrayType>::value&&
4039is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4040is_detected<range_value_t, ConstructibleArrayType>::value&&
4041// special case for types like std::filesystem::path whose iterator's value_type are themselves
4042// c.f. https://github.com/nlohmann/json/pull/3073
4043!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4045detected_t<range_value_t, ConstructibleArrayType >>::value >>
4046{
4047 using value_type = range_value_t<ConstructibleArrayType>;
4048
4049 static constexpr bool value =
4050 std::is_same<value_type,
4051 typename BasicJsonType::array_t::value_type>::value ||
4052 has_from_json<BasicJsonType,
4053 value_type>::value ||
4055 BasicJsonType,
4056 value_type >::value;
4057};
4058
4059template<typename BasicJsonType, typename ConstructibleArrayType>
4061 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4062
4063template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4064 typename = void>
4065struct is_compatible_integer_type_impl : std::false_type {};
4066
4067template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4069 RealIntegerType, CompatibleNumberIntegerType,
4070 enable_if_t < std::is_integral<RealIntegerType>::value&&
4071 std::is_integral<CompatibleNumberIntegerType>::value&&
4072 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4073{
4074 // is there an assert somewhere on overflows?
4075 using RealLimits = std::numeric_limits<RealIntegerType>;
4076 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4077
4078 static constexpr auto value =
4079 is_constructible<RealIntegerType,
4080 CompatibleNumberIntegerType>::value &&
4081 CompatibleLimits::is_integer &&
4082 RealLimits::is_signed == CompatibleLimits::is_signed;
4083};
4084
4085template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4087 : is_compatible_integer_type_impl<RealIntegerType,
4088 CompatibleNumberIntegerType> {};
4089
4090template<typename BasicJsonType, typename CompatibleType, typename = void>
4091struct is_compatible_type_impl: std::false_type {};
4092
4093template<typename BasicJsonType, typename CompatibleType>
4095 BasicJsonType, CompatibleType,
4096 enable_if_t<is_complete_type<CompatibleType>::value >>
4097{
4098 static constexpr bool value =
4100};
4101
4102template<typename BasicJsonType, typename CompatibleType>
4104 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4105
4106template<typename T1, typename T2>
4107struct is_constructible_tuple : std::false_type {};
4108
4109template<typename T1, typename... Args>
4110struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4111
4112template<typename BasicJsonType, typename T>
4113struct is_json_iterator_of : std::false_type {};
4114
4115template<typename BasicJsonType>
4116struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4117
4118template<typename BasicJsonType>
4119struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4120{};
4121
4122// checks if a given type T is a template specialization of Primary
4123template<template <typename...> class Primary, typename T>
4124struct is_specialization_of : std::false_type {};
4125
4126template<template <typename...> class Primary, typename... Args>
4127struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4128
4129template<typename T>
4131
4132// checks if B is a json_pointer<A>
4133template <typename A, typename B>
4134struct is_json_pointer_of : std::false_type {};
4135
4136template <typename A>
4137struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>> : std::true_type {};
4138
4139template <typename A>
4140struct is_json_pointer_of<A, ::nlohmann::json_pointer<A>&> : std::true_type {};
4141
4142// checks if A and B are comparable using Compare functor
4143template<typename Compare, typename A, typename B, typename = void>
4144struct is_comparable : std::false_type {};
4145
4146// We exclude json_pointer here, because the checks using Compare(A, B) will
4147// use json_pointer::operator string_t() which triggers a deprecation warning
4148// for GCC. See https://github.com/nlohmann/json/issues/4621. The call to
4149// is_json_pointer_of can be removed once the deprecated function has been
4150// removed.
4151template<typename Compare, typename A, typename B>
4152struct is_comparable < Compare, A, B, enable_if_t < !is_json_pointer_of<A, B>::value
4153&& std::is_constructible <decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>()))>::value
4154&& std::is_constructible <decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>::value
4155>> : std::true_type {};
4156
4157template<typename T>
4158using detect_is_transparent = typename T::is_transparent;
4159
4160// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4161// see is_usable_as_basic_json_key_type below
4162template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4163 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4164using is_usable_as_key_type = typename std::conditional <
4166 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4167 ObjectKeyType>::value)
4168 && (!RequireTransparentComparator
4169 || is_detected <detect_is_transparent, Comparator>::value)
4170 && !is_json_pointer<KeyType>::value,
4171 std::true_type,
4172 std::false_type >::type;
4173
4174// type trait to check if KeyType can be used as an object key
4175// true if:
4176// - KeyType is comparable with BasicJsonType::object_t::key_type
4177// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4178// - the comparator is transparent or RequireTransparentComparator is false
4179// - KeyType is not a JSON iterator or json_pointer
4180template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4181 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4182using is_usable_as_basic_json_key_type = typename std::conditional <
4183 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4184 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4185 RequireTransparentComparator, ExcludeObjectKeyType>::value
4187 std::true_type,
4188 std::false_type >::type;
4189
4190template<typename ObjectType, typename KeyType>
4191using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4192
4193// type trait to check if object_t has an erase() member functions accepting KeyType
4194template<typename BasicJsonType, typename KeyType>
4195using has_erase_with_key_type = typename std::conditional <
4196 is_detected <
4197 detect_erase_with_key_type,
4198 typename BasicJsonType::object_t, KeyType >::value,
4199 std::true_type,
4200 std::false_type >::type;
4201
4202// a naive helper to check if a type is an ordered_map (exploits the fact that
4203// ordered_map inherits capacity() from std::vector)
4204template <typename T>
4206{
4207 using one = char;
4208
4209 struct two
4210 {
4211 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4212 };
4213
4214 template <typename C> static one test( decltype(&C::capacity) ) ;
4215 template <typename C> static two test(...);
4216
4217 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-use-enum-class)
4218};
4219
4220// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4221template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4222T conditional_static_cast(U value)
4223{
4224 return static_cast<T>(value);
4225}
4226
4227template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4228T conditional_static_cast(U value)
4229{
4230 return value;
4231}
4232
4233template<typename... Types>
4234using all_integral = conjunction<std::is_integral<Types>...>;
4235
4236template<typename... Types>
4237using all_signed = conjunction<std::is_signed<Types>...>;
4238
4239template<typename... Types>
4240using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4241
4242// there's a disjunction trait in another PR; replace when merged
4243template<typename... Types>
4244using same_sign = std::integral_constant < bool,
4245 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4246
4247template<typename OfType, typename T>
4248using never_out_of_range = std::integral_constant < bool,
4249 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4250 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4251
4252template<typename OfType, typename T,
4253 bool OfTypeSigned = std::is_signed<OfType>::value,
4254 bool TSigned = std::is_signed<T>::value>
4256
4257template<typename OfType, typename T>
4258struct value_in_range_of_impl2<OfType, T, false, false>
4259{
4260 static constexpr bool test(T val)
4261 {
4262 using CommonType = typename std::common_type<OfType, T>::type;
4263 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4264 }
4265};
4266
4267template<typename OfType, typename T>
4268struct value_in_range_of_impl2<OfType, T, true, false>
4269{
4270 static constexpr bool test(T val)
4271 {
4272 using CommonType = typename std::common_type<OfType, T>::type;
4273 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4274 }
4275};
4276
4277template<typename OfType, typename T>
4278struct value_in_range_of_impl2<OfType, T, false, true>
4279{
4280 static constexpr bool test(T val)
4281 {
4282 using CommonType = typename std::common_type<OfType, T>::type;
4283 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4284 }
4285};
4286
4287template<typename OfType, typename T>
4288struct value_in_range_of_impl2<OfType, T, true, true>
4289{
4290 static constexpr bool test(T val)
4291 {
4292 using CommonType = typename std::common_type<OfType, T>::type;
4293 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4294 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4295 }
4296};
4297
4298template<typename OfType, typename T,
4299 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4300 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4302
4303template<typename OfType, typename T>
4304struct value_in_range_of_impl1<OfType, T, false>
4305{
4306 static constexpr bool test(T val)
4307 {
4309 }
4310};
4311
4312template<typename OfType, typename T>
4313struct value_in_range_of_impl1<OfType, T, true>
4314{
4315 static constexpr bool test(T /*val*/)
4316 {
4317 return true;
4318 }
4319};
4320
4321template<typename OfType, typename T>
4322constexpr bool value_in_range_of(T val)
4323{
4325}
4326
4327template<bool Value>
4328using bool_constant = std::integral_constant<bool, Value>;
4329
4331// is_c_string
4333
4334namespace impl
4335{
4336
4337template<typename T>
4338constexpr bool is_c_string()
4339{
4340 using TUnExt = typename std::remove_extent<T>::type;
4341 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4342 using TUnPtr = typename std::remove_pointer<T>::type;
4343 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4344 return
4345 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4346 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4347}
4348
4349} // namespace impl
4350
4351// checks whether T is a [cv] char */[cv] char[] C string
4352template<typename T>
4353struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4354
4355template<typename T>
4356using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4357
4359// is_transparent
4361
4362namespace impl
4363{
4364
4365template<typename T>
4366constexpr bool is_transparent()
4367{
4368 return is_detected<detect_is_transparent, T>::value;
4369}
4370
4371} // namespace impl
4372
4373// checks whether T has a member named is_transparent
4374template<typename T>
4375struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4376
4378
4379} // namespace detail
4380NLOHMANN_JSON_NAMESPACE_END
4381
4382// #include <nlohmann/detail/string_concat.hpp>
4383// __ _____ _____ _____
4384// __| | __| | | | JSON for Modern C++
4385// | | |__ | | | | | | version 3.12.0
4386// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4387//
4388// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
4389// SPDX-License-Identifier: MIT
4390
4391
4392
4393#include <cstring> // strlen
4394#include <string> // string
4395#include <utility> // forward
4396
4397// #include <nlohmann/detail/meta/cpp_future.hpp>
4398
4399// #include <nlohmann/detail/meta/detected.hpp>
4400
4401
4402NLOHMANN_JSON_NAMESPACE_BEGIN
4403namespace detail
4404{
4405
4406inline std::size_t concat_length()
4407{
4408 return 0;
4409}
4410
4411template<typename... Args>
4412inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4413
4414template<typename StringType, typename... Args>
4415inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4416
4417template<typename... Args>
4418inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4419{
4420 return 1 + concat_length(rest...);
4421}
4422
4423template<typename... Args>
4424inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4425{
4426 // cppcheck-suppress ignoredReturnValue
4427 return ::strlen(cstr) + concat_length(rest...);
4428}
4429
4430template<typename StringType, typename... Args>
4431inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4432{
4433 return str.size() + concat_length(rest...);
4434}
4435
4436template<typename OutStringType>
4437inline void concat_into(OutStringType& /*out*/)
4438{}
4439
4440template<typename StringType, typename Arg>
4441using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4442
4443template<typename StringType, typename Arg>
4444using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4445
4446template<typename StringType, typename Arg>
4447using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4448
4449template<typename StringType, typename Arg>
4450using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4451
4452template<typename StringType, typename Arg>
4453using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4454
4455template<typename StringType, typename Arg>
4456using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4457
4458template<typename StringType, typename Arg>
4459using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4460
4461template<typename StringType, typename Arg>
4462using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
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, int > = 0 >
4467inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4468
4469template < typename OutStringType, typename Arg, typename... Args,
4470 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4471 && !detect_string_can_append_op<OutStringType, Arg>::value
4472 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4473inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4474
4475template < typename OutStringType, typename Arg, typename... Args,
4476 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4477 && !detect_string_can_append_op<OutStringType, Arg>::value
4478 && !detect_string_can_append_iter<OutStringType, Arg>::value
4479 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4480inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4481
4482template<typename OutStringType, typename Arg, typename... Args,
4483 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4484inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4485{
4486 out.append(std::forward<Arg>(arg));
4487 concat_into(out, std::forward<Args>(rest)...);
4488}
4489
4490template < typename OutStringType, typename Arg, typename... Args,
4491 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4492 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4493inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4494{
4495 out += std::forward<Arg>(arg);
4496 concat_into(out, std::forward<Args>(rest)...);
4497}
4498
4499template < typename OutStringType, typename Arg, typename... Args,
4500 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4501 && !detect_string_can_append_op<OutStringType, Arg>::value
4502 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4503inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4504{
4505 out.append(arg.begin(), arg.end());
4506 concat_into(out, std::forward<Args>(rest)...);
4507}
4508
4509template < typename OutStringType, typename Arg, typename... Args,
4510 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4511 && !detect_string_can_append_op<OutStringType, Arg>::value
4512 && !detect_string_can_append_iter<OutStringType, Arg>::value
4513 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4514inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4515{
4516 out.append(arg.data(), arg.size());
4517 concat_into(out, std::forward<Args>(rest)...);
4518}
4519
4520template<typename OutStringType = std::string, typename... Args>
4521inline OutStringType concat(Args && ... args)
4522{
4523 OutStringType str;
4524 str.reserve(concat_length(args...));
4525 concat_into(str, std::forward<Args>(args)...);
4526 return str;
4527}
4528
4529} // namespace detail
4530NLOHMANN_JSON_NAMESPACE_END
4531
4532
4533// With -Wweak-vtables, Clang will complain about the exception classes as they
4534// have no out-of-line virtual method definitions and their vtable will be
4535// emitted in every translation unit. This issue cannot be fixed with a
4536// header-only library as there is no implementation file to move these
4537// functions to. As a result, we suppress this warning here to avoid client
4538// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4539// for a discussion.
4540#if defined(__clang__)
4541 #pragma clang diagnostic push
4542 #pragma clang diagnostic ignored "-Wweak-vtables"
4543#endif
4544
4545NLOHMANN_JSON_NAMESPACE_BEGIN
4546namespace detail
4547{
4548
4550// exceptions //
4552
4555class exception : public std::exception
4556{
4557 public:
4559 const char* what() const noexcept override
4560 {
4561 return m.what();
4562 }
4563
4565 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4566
4567 protected:
4568 JSON_HEDLEY_NON_NULL(3)
4569 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4570
4571 static std::string name(const std::string& ename, int id_)
4572 {
4573 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4574 }
4575
4576 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4577 {
4578 return "";
4579 }
4580
4581 template<typename BasicJsonType>
4582 static std::string diagnostics(const BasicJsonType* leaf_element)
4583 {
4584#if JSON_DIAGNOSTICS
4585 std::vector<std::string> tokens;
4586 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4587 {
4588 switch (current->m_parent->type())
4589 {
4590 case value_t::array:
4591 {
4592 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4593 {
4594 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4595 {
4596 tokens.emplace_back(std::to_string(i));
4597 break;
4598 }
4599 }
4600 break;
4601 }
4602
4603 case value_t::object:
4604 {
4605 for (const auto& element : *current->m_parent->m_data.m_value.object)
4606 {
4607 if (&element.second == current)
4608 {
4609 tokens.emplace_back(element.first.c_str());
4610 break;
4611 }
4612 }
4613 break;
4614 }
4615
4616 case value_t::null: // LCOV_EXCL_LINE
4617 case value_t::string: // LCOV_EXCL_LINE
4618 case value_t::boolean: // LCOV_EXCL_LINE
4619 case value_t::number_integer: // LCOV_EXCL_LINE
4620 case value_t::number_unsigned: // LCOV_EXCL_LINE
4621 case value_t::number_float: // LCOV_EXCL_LINE
4622 case value_t::binary: // LCOV_EXCL_LINE
4623 case value_t::discarded: // LCOV_EXCL_LINE
4624 default: // LCOV_EXCL_LINE
4625 break; // LCOV_EXCL_LINE
4626 }
4627 }
4628
4629 if (tokens.empty())
4630 {
4631 return "";
4632 }
4633
4634 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4635 [](const std::string & a, const std::string & b)
4636 {
4637 return concat(a, '/', detail::escape(b));
4638 });
4639
4640 return concat('(', str, ") ", get_byte_positions(leaf_element));
4641#else
4642 return get_byte_positions(leaf_element);
4643#endif
4644 }
4645
4646 private:
4648 std::runtime_error m;
4649#if JSON_DIAGNOSTIC_POSITIONS
4650 template<typename BasicJsonType>
4651 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4652 {
4653 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4654 {
4655 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4656 }
4657 return "";
4658 }
4659#else
4660 template<typename BasicJsonType>
4661 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4662 {
4663 static_cast<void>(leaf_element);
4664 return "";
4665 }
4666#endif
4667};
4668
4671class parse_error : public exception
4672{
4673 public:
4683 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4684 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4685 {
4686 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4687 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4688 return {id_, pos.chars_read_total, w.c_str()};
4689 }
4690
4691 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4692 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4693 {
4694 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4695 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4696 ": ", exception::diagnostics(context), what_arg);
4697 return {id_, byte_, w.c_str()};
4698 }
4699
4709 const std::size_t byte;
4710
4711 private:
4712 parse_error(int id_, std::size_t byte_, const char* what_arg)
4713 : exception(id_, what_arg), byte(byte_) {}
4714
4715 static std::string position_string(const position_t& pos)
4716 {
4717 return concat(" at line ", std::to_string(pos.lines_read + 1),
4718 ", column ", std::to_string(pos.chars_read_current_line));
4719 }
4720};
4721
4724class invalid_iterator : public exception
4725{
4726 public:
4727 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4728 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4729 {
4730 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4731 return {id_, w.c_str()};
4732 }
4733
4734 private:
4735 JSON_HEDLEY_NON_NULL(3)
4736 invalid_iterator(int id_, const char* what_arg)
4737 : exception(id_, what_arg) {}
4738};
4739
4742class type_error : public exception
4743{
4744 public:
4745 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4746 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4747 {
4748 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4749 return {id_, w.c_str()};
4750 }
4751
4752 private:
4753 JSON_HEDLEY_NON_NULL(3)
4754 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4755};
4756
4759class out_of_range : public exception
4760{
4761 public:
4762 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4763 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4764 {
4765 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4766 return {id_, w.c_str()};
4767 }
4768
4769 private:
4770 JSON_HEDLEY_NON_NULL(3)
4771 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4772};
4773
4776class other_error : public exception
4777{
4778 public:
4779 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4780 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4781 {
4782 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4783 return {id_, w.c_str()};
4784 }
4785
4786 private:
4787 JSON_HEDLEY_NON_NULL(3)
4788 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4789};
4790
4791} // namespace detail
4792NLOHMANN_JSON_NAMESPACE_END
4793
4794#if defined(__clang__)
4795 #pragma clang diagnostic pop
4796#endif
4797
4798// #include <nlohmann/detail/macro_scope.hpp>
4799
4800// #include <nlohmann/detail/meta/cpp_future.hpp>
4801
4802// #include <nlohmann/detail/meta/identity_tag.hpp>
4803// __ _____ _____ _____
4804// __| | __| | | | JSON for Modern C++
4805// | | |__ | | | | | | version 3.12.0
4806// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4807//
4808// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
4809// SPDX-License-Identifier: MIT
4810
4811
4812
4813// #include <nlohmann/detail/abi_macros.hpp>
4814
4815
4816NLOHMANN_JSON_NAMESPACE_BEGIN
4817namespace detail
4818{
4819
4820// dispatching helper struct
4821template <class T> struct identity_tag {};
4822
4823} // namespace detail
4824NLOHMANN_JSON_NAMESPACE_END
4825
4826// #include <nlohmann/detail/meta/std_fs.hpp>
4827// __ _____ _____ _____
4828// __| | __| | | | JSON for Modern C++
4829// | | |__ | | | | | | version 3.12.0
4830// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4831//
4832// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
4833// SPDX-License-Identifier: MIT
4834
4835
4836
4837// #include <nlohmann/detail/macro_scope.hpp>
4838
4839
4840#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4841#include <experimental/filesystem>
4842NLOHMANN_JSON_NAMESPACE_BEGIN
4843namespace detail
4844{
4845namespace std_fs = std::experimental::filesystem;
4846} // namespace detail
4847NLOHMANN_JSON_NAMESPACE_END
4848#elif JSON_HAS_FILESYSTEM
4849#include <filesystem> // NOLINT(build/c++17)
4850NLOHMANN_JSON_NAMESPACE_BEGIN
4851namespace detail
4852{
4853namespace std_fs = std::filesystem;
4854} // namespace detail
4855NLOHMANN_JSON_NAMESPACE_END
4856#endif
4857
4858// #include <nlohmann/detail/meta/type_traits.hpp>
4859
4860// #include <nlohmann/detail/string_concat.hpp>
4861
4862// #include <nlohmann/detail/value_t.hpp>
4863
4864
4865// include after macro_scope.hpp
4866#ifdef JSON_HAS_CPP_17
4867 #include <optional> // optional
4868#endif
4869
4870#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4871 #include <string_view> // u8string_view
4872#endif
4873
4874NLOHMANN_JSON_NAMESPACE_BEGIN
4875namespace detail
4876{
4877
4878template<typename BasicJsonType>
4879inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4880{
4881 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4882 {
4883 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4884 }
4885 n = nullptr;
4886}
4887
4888#ifdef JSON_HAS_CPP_17
4889template<typename BasicJsonType, typename T>
4890void from_json(const BasicJsonType& j, std::optional<T>& opt)
4891{
4892 if (j.is_null())
4893 {
4894 opt = std::nullopt;
4895 }
4896 else
4897 {
4898 opt.emplace(j.template get<T>());
4899 }
4900}
4901#endif // JSON_HAS_CPP_17
4902
4903// overloads for basic_json template parameters
4904template < typename BasicJsonType, typename ArithmeticType,
4905 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4906 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4907 int > = 0 >
4908void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4909{
4910 switch (static_cast<value_t>(j))
4911 {
4913 {
4914 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4915 break;
4916 }
4918 {
4919 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4920 break;
4921 }
4923 {
4924 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4925 break;
4926 }
4927
4928 case value_t::null:
4929 case value_t::object:
4930 case value_t::array:
4931 case value_t::string:
4932 case value_t::boolean:
4933 case value_t::binary:
4934 case value_t::discarded:
4935 default:
4936 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4937 }
4938}
4939
4940template<typename BasicJsonType>
4941inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4942{
4943 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4944 {
4945 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4946 }
4947 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4948}
4949
4950template<typename BasicJsonType>
4951inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4952{
4953 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4954 {
4955 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4956 }
4957 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4958}
4959
4960template <
4961 typename BasicJsonType, typename StringType,
4962 enable_if_t <
4963 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4964 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4965 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4966 && !is_json_ref<StringType>::value, int > = 0 >
4967inline void from_json(const BasicJsonType& j, StringType& s)
4968{
4969 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4970 {
4971 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4972 }
4973
4974 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4975}
4976
4977template<typename BasicJsonType>
4978inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4979{
4980 get_arithmetic_value(j, val);
4981}
4982
4983template<typename BasicJsonType>
4984inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4985{
4986 get_arithmetic_value(j, val);
4987}
4988
4989template<typename BasicJsonType>
4990inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4991{
4992 get_arithmetic_value(j, val);
4993}
4994
4995#if !JSON_DISABLE_ENUM_SERIALIZATION
4996template<typename BasicJsonType, typename EnumType,
4997 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4998inline void from_json(const BasicJsonType& j, EnumType& e)
4999{
5000 typename std::underlying_type<EnumType>::type val;
5001 get_arithmetic_value(j, val);
5002 e = static_cast<EnumType>(val);
5003}
5004#endif // JSON_DISABLE_ENUM_SERIALIZATION
5005
5006// forward_list doesn't have an insert method
5007template<typename BasicJsonType, typename T, typename Allocator,
5008 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5009inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
5010{
5011 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5012 {
5013 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5014 }
5015 l.clear();
5016 std::transform(j.rbegin(), j.rend(),
5017 std::front_inserter(l), [](const BasicJsonType & i)
5018 {
5019 return i.template get<T>();
5020 });
5021}
5022
5023// valarray doesn't have an insert method
5024template<typename BasicJsonType, typename T,
5025 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5026inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5027{
5028 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5029 {
5030 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5031 }
5032 l.resize(j.size());
5033 std::transform(j.begin(), j.end(), std::begin(l),
5034 [](const BasicJsonType & elem)
5035 {
5036 return elem.template get<T>();
5037 });
5038}
5039
5040template<typename BasicJsonType, typename T, std::size_t N>
5041auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5042-> decltype(j.template get<T>(), void())
5043{
5044 for (std::size_t i = 0; i < N; ++i)
5045 {
5046 arr[i] = j.at(i).template get<T>();
5047 }
5048}
5049
5050template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5051auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5052-> decltype(j.template get<T>(), void())
5053{
5054 for (std::size_t i1 = 0; i1 < N1; ++i1)
5055 {
5056 for (std::size_t i2 = 0; i2 < N2; ++i2)
5057 {
5058 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5059 }
5060 }
5061}
5062
5063template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5064auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5065-> decltype(j.template get<T>(), void())
5066{
5067 for (std::size_t i1 = 0; i1 < N1; ++i1)
5068 {
5069 for (std::size_t i2 = 0; i2 < N2; ++i2)
5070 {
5071 for (std::size_t i3 = 0; i3 < N3; ++i3)
5072 {
5073 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5074 }
5075 }
5076 }
5077}
5078
5079template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5080auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5081-> decltype(j.template get<T>(), void())
5082{
5083 for (std::size_t i1 = 0; i1 < N1; ++i1)
5084 {
5085 for (std::size_t i2 = 0; i2 < N2; ++i2)
5086 {
5087 for (std::size_t i3 = 0; i3 < N3; ++i3)
5088 {
5089 for (std::size_t i4 = 0; i4 < N4; ++i4)
5090 {
5091 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5092 }
5093 }
5094 }
5095 }
5096}
5097
5098template<typename BasicJsonType>
5099inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5100{
5101 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5102}
5103
5104template<typename BasicJsonType, typename T, std::size_t N>
5105auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5106 priority_tag<2> /*unused*/)
5107-> decltype(j.template get<T>(), void())
5108{
5109 for (std::size_t i = 0; i < N; ++i)
5110 {
5111 arr[i] = j.at(i).template get<T>();
5112 }
5113}
5114
5115template<typename BasicJsonType, typename ConstructibleArrayType,
5116 enable_if_t<
5117 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5118 int> = 0>
5119auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5120-> decltype(
5121 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5122 j.template get<typename ConstructibleArrayType::value_type>(),
5123 void())
5124{
5125 using std::end;
5126
5127 ConstructibleArrayType ret;
5128 ret.reserve(j.size());
5129 std::transform(j.begin(), j.end(),
5130 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5131 {
5132 // get<BasicJsonType>() returns *this, this won't call a from_json
5133 // method when value_type is BasicJsonType
5134 return i.template get<typename ConstructibleArrayType::value_type>();
5135 });
5136 arr = std::move(ret);
5137}
5138
5139template<typename BasicJsonType, typename ConstructibleArrayType,
5140 enable_if_t<
5141 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5142 int> = 0>
5143inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5144 priority_tag<0> /*unused*/)
5145{
5146 using std::end;
5147
5148 ConstructibleArrayType ret;
5149 std::transform(
5150 j.begin(), j.end(), std::inserter(ret, end(ret)),
5151 [](const BasicJsonType & i)
5152 {
5153 // get<BasicJsonType>() returns *this, this won't call a from_json
5154 // method when value_type is BasicJsonType
5155 return i.template get<typename ConstructibleArrayType::value_type>();
5156 });
5157 arr = std::move(ret);
5158}
5159
5160template < typename BasicJsonType, typename ConstructibleArrayType,
5161 enable_if_t <
5164 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
5165 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5167 int > = 0 >
5168auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5169-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5170j.template get<typename ConstructibleArrayType::value_type>(),
5171void())
5172{
5173 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5174 {
5175 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5176 }
5177
5178 from_json_array_impl(j, arr, priority_tag<3> {});
5179}
5180
5181template < typename BasicJsonType, typename T, std::size_t... Idx >
5182std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5183 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5184{
5185 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5186}
5187
5188template < typename BasicJsonType, typename T, std::size_t N >
5189auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5190-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5191{
5192 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5193 {
5194 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5195 }
5196
5197 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5198}
5199
5200template<typename BasicJsonType>
5201inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5202{
5203 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5204 {
5205 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5206 }
5207
5208 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5209}
5210
5211template<typename BasicJsonType, typename ConstructibleObjectType,
5212 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5213inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5214{
5215 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5216 {
5217 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5218 }
5219
5220 ConstructibleObjectType ret;
5221 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5222 using value_type = typename ConstructibleObjectType::value_type;
5223 std::transform(
5224 inner_object->begin(), inner_object->end(),
5225 std::inserter(ret, ret.begin()),
5226 [](typename BasicJsonType::object_t::value_type const & p)
5227 {
5228 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5229 });
5230 obj = std::move(ret);
5231}
5232
5233// overload for arithmetic types, not chosen for basic_json template arguments
5234// (BooleanType, etc.); note: Is it really necessary to provide explicit
5235// overloads for boolean_t etc. in case of a custom BooleanType which is not
5236// an arithmetic type?
5237template < typename BasicJsonType, typename ArithmeticType,
5238 enable_if_t <
5239 std::is_arithmetic<ArithmeticType>::value&&
5240 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5241 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5242 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5243 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5244 int > = 0 >
5245inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5246{
5247 switch (static_cast<value_t>(j))
5248 {
5250 {
5251 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5252 break;
5253 }
5255 {
5256 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5257 break;
5258 }
5260 {
5261 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5262 break;
5263 }
5264 case value_t::boolean:
5265 {
5266 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5267 break;
5268 }
5269
5270 case value_t::null:
5271 case value_t::object:
5272 case value_t::array:
5273 case value_t::string:
5274 case value_t::binary:
5275 case value_t::discarded:
5276 default:
5277 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5278 }
5279}
5280
5281template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5282std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5283{
5284 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5285}
5286
5287template<typename BasicJsonType>
5288std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5289{
5290 return {};
5291}
5292
5293template < typename BasicJsonType, class A1, class A2 >
5294std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5295{
5296 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5297 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5298}
5299
5300template<typename BasicJsonType, typename A1, typename A2>
5301inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5302{
5303 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5304}
5305
5306template<typename BasicJsonType, typename... Args>
5307std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5308{
5309 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5310}
5311
5312template<typename BasicJsonType, typename... Args>
5313inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5314{
5315 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5316}
5317
5318template<typename BasicJsonType, typename TupleRelated>
5319auto from_json(BasicJsonType&& j, TupleRelated&& t)
5320-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5321{
5322 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5323 {
5324 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5325 }
5326
5327 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5328}
5329
5330template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5331 typename = enable_if_t < !std::is_constructible <
5332 typename BasicJsonType::string_t, Key >::value >>
5333inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5334{
5335 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5336 {
5337 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5338 }
5339 m.clear();
5340 for (const auto& p : j)
5341 {
5342 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5343 {
5344 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5345 }
5346 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5347 }
5348}
5349
5350template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5351 typename = enable_if_t < !std::is_constructible <
5352 typename BasicJsonType::string_t, Key >::value >>
5353inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5354{
5355 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5356 {
5357 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5358 }
5359 m.clear();
5360 for (const auto& p : j)
5361 {
5362 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5363 {
5364 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5365 }
5366 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5367 }
5368}
5369
5370#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5371template<typename BasicJsonType>
5372inline void from_json(const BasicJsonType& j, std_fs::path& p)
5373{
5374 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5375 {
5376 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5377 }
5378 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5379 // Checking for C++20 standard or later can be insufficient in case the
5380 // library support for char8_t is either incomplete or was disabled
5381 // altogether. Use the __cpp_lib_char8_t feature test instead.
5382#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5383 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5384#else
5385 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5386#endif
5387}
5388#endif
5389
5391{
5392 template<typename BasicJsonType, typename T>
5393 auto operator()(const BasicJsonType& j, T&& val) const
5394 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5395 -> decltype(from_json(j, std::forward<T>(val)))
5396 {
5397 return from_json(j, std::forward<T>(val));
5398 }
5399};
5400
5401} // namespace detail
5402
5403#ifndef JSON_HAS_CPP_17
5407namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5408{
5409#endif
5410JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5411 detail::static_const<detail::from_json_fn>::value;
5412#ifndef JSON_HAS_CPP_17
5413} // namespace
5414#endif
5415
5416NLOHMANN_JSON_NAMESPACE_END
5417
5418// #include <nlohmann/detail/conversions/to_json.hpp>
5419// __ _____ _____ _____
5420// __| | __| | | | JSON for Modern C++
5421// | | |__ | | | | | | version 3.12.0
5422// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5423//
5424// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
5425// SPDX-License-Identifier: MIT
5426
5427
5428
5429// #include <nlohmann/detail/macro_scope.hpp>
5430// JSON_HAS_CPP_17
5431#ifdef JSON_HAS_CPP_17
5432 #include <optional> // optional
5433#endif
5434
5435#include <algorithm> // copy
5436#include <iterator> // begin, end
5437#include <memory> // allocator_traits
5438#include <string> // basic_string, char_traits
5439#include <tuple> // tuple, get
5440#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5441#include <utility> // move, forward, declval, pair
5442#include <valarray> // valarray
5443#include <vector> // vector
5444
5445// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5446// __ _____ _____ _____
5447// __| | __| | | | JSON for Modern C++
5448// | | |__ | | | | | | version 3.12.0
5449// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5450//
5451// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
5452// SPDX-License-Identifier: MIT
5453
5454
5455
5456#include <cstddef> // size_t
5457#include <iterator> // forward_iterator_tag
5458#include <tuple> // tuple_size, get, tuple_element
5459#include <utility> // move
5460
5461#if JSON_HAS_RANGES
5462 #include <ranges> // enable_borrowed_range
5463#endif
5464
5465// #include <nlohmann/detail/abi_macros.hpp>
5466
5467// #include <nlohmann/detail/meta/type_traits.hpp>
5468
5469// #include <nlohmann/detail/string_utils.hpp>
5470// __ _____ _____ _____
5471// __| | __| | | | JSON for Modern C++
5472// | | |__ | | | | | | version 3.12.0
5473// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5474//
5475// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
5476// SPDX-License-Identifier: MIT
5477
5478
5479
5480#include <cstddef> // size_t
5481#include <string> // string, to_string
5482
5483// #include <nlohmann/detail/abi_macros.hpp>
5484
5485
5486NLOHMANN_JSON_NAMESPACE_BEGIN
5487namespace detail
5488{
5489
5490template<typename StringType>
5491void int_to_string(StringType& target, std::size_t value)
5492{
5493 // For ADL
5494 using std::to_string;
5495 target = to_string(value);
5496}
5497
5498template<typename StringType>
5499StringType to_string(std::size_t value)
5500{
5501 StringType result;
5502 int_to_string(result, value);
5503 return result;
5504}
5505
5506} // namespace detail
5507NLOHMANN_JSON_NAMESPACE_END
5508
5509// #include <nlohmann/detail/value_t.hpp>
5510
5511
5512NLOHMANN_JSON_NAMESPACE_BEGIN
5513namespace detail
5514{
5515
5516template<typename IteratorType> class iteration_proxy_value
5517{
5518 public:
5519 using difference_type = std::ptrdiff_t;
5520 using value_type = iteration_proxy_value;
5521 using pointer = value_type *;
5522 using reference = value_type &;
5523 using iterator_category = std::forward_iterator_tag;
5524 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5525
5526 private:
5528 IteratorType anchor{};
5530 std::size_t array_index = 0;
5532 mutable std::size_t array_index_last = 0;
5534 mutable string_type array_index_str = "0";
5536 string_type empty_str{};
5537
5538 public:
5539 explicit iteration_proxy_value() = default;
5540 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5541 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5542 && std::is_nothrow_default_constructible<string_type>::value)
5543 : anchor(std::move(it))
5544 , array_index(array_index_)
5545 {}
5546
5547 iteration_proxy_value(iteration_proxy_value const&) = default;
5548 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5549 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5550 iteration_proxy_value(iteration_proxy_value&&)
5551 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5552 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5553 iteration_proxy_value& operator=(iteration_proxy_value&&)
5554 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5555 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5556 ~iteration_proxy_value() = default;
5557
5559 const iteration_proxy_value& operator*() const
5560 {
5561 return *this;
5562 }
5563
5565 iteration_proxy_value& operator++()
5566 {
5567 ++anchor;
5568 ++array_index;
5569
5570 return *this;
5571 }
5572
5573 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5574 {
5575 auto tmp = iteration_proxy_value(anchor, array_index);
5576 ++anchor;
5577 ++array_index;
5578 return tmp;
5579 }
5580
5582 bool operator==(const iteration_proxy_value& o) const
5583 {
5584 return anchor == o.anchor;
5585 }
5586
5588 bool operator!=(const iteration_proxy_value& o) const
5589 {
5590 return anchor != o.anchor;
5591 }
5592
5594 const string_type& key() const
5595 {
5596 JSON_ASSERT(anchor.m_object != nullptr);
5597
5598 switch (anchor.m_object->type())
5599 {
5600 // use integer array index as key
5601 case value_t::array:
5602 {
5603 if (array_index != array_index_last)
5604 {
5605 int_to_string( array_index_str, array_index );
5606 array_index_last = array_index;
5607 }
5608 return array_index_str;
5609 }
5610
5611 // use key from the object
5612 case value_t::object:
5613 return anchor.key();
5614
5615 // use an empty key for all primitive types
5616 case value_t::null:
5617 case value_t::string:
5618 case value_t::boolean:
5622 case value_t::binary:
5623 case value_t::discarded:
5624 default:
5625 return empty_str;
5626 }
5627 }
5628
5630 typename IteratorType::reference value() const
5631 {
5632 return anchor.value();
5633 }
5634};
5635
5637template<typename IteratorType> class iteration_proxy
5638{
5639 private:
5641 typename IteratorType::pointer container = nullptr;
5642
5643 public:
5644 explicit iteration_proxy() = default;
5645
5647 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5648 : container(&cont) {}
5649
5650 iteration_proxy(iteration_proxy const&) = default;
5651 iteration_proxy& operator=(iteration_proxy const&) = default;
5652 iteration_proxy(iteration_proxy&&) noexcept = default;
5653 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5654 ~iteration_proxy() = default;
5655
5657 iteration_proxy_value<IteratorType> begin() const noexcept
5658 {
5659 return iteration_proxy_value<IteratorType>(container->begin());
5660 }
5661
5664 {
5665 return iteration_proxy_value<IteratorType>(container->end());
5666 }
5667};
5668
5669// Structured Bindings Support
5670// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5671// And see https://github.com/nlohmann/json/pull/1391
5672template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5673auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5674{
5675 return i.key();
5676}
5677// Structured Bindings Support
5678// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5679// And see https://github.com/nlohmann/json/pull/1391
5680template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5681auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5682{
5683 return i.value();
5684}
5685
5686} // namespace detail
5687NLOHMANN_JSON_NAMESPACE_END
5688
5689// The Addition to the STD Namespace is required to add
5690// Structured Bindings Support to the iteration_proxy_value class
5691// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5692// And see https://github.com/nlohmann/json/pull/1391
5693namespace std
5694{
5695
5696#if defined(__clang__)
5697 // Fix: https://github.com/nlohmann/json/issues/1401
5698 #pragma clang diagnostic push
5699 #pragma clang diagnostic ignored "-Wmismatched-tags"
5700#endif
5701template<typename IteratorType>
5702class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5703 : public std::integral_constant<std::size_t, 2> {};
5704
5705template<std::size_t N, typename IteratorType>
5706class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5707{
5708 public:
5709 using type = decltype(
5710 get<N>(std::declval <
5711 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5712};
5713#if defined(__clang__)
5714 #pragma clang diagnostic pop
5715#endif
5716
5717} // namespace std
5718
5719#if JSON_HAS_RANGES
5720 template <typename IteratorType>
5721 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5722#endif
5723
5724// #include <nlohmann/detail/meta/cpp_future.hpp>
5725
5726// #include <nlohmann/detail/meta/std_fs.hpp>
5727
5728// #include <nlohmann/detail/meta/type_traits.hpp>
5729
5730// #include <nlohmann/detail/value_t.hpp>
5731
5732
5733NLOHMANN_JSON_NAMESPACE_BEGIN
5734namespace detail
5735{
5736
5738// constructors //
5740
5741/*
5742 * Note all external_constructor<>::construct functions need to call
5743 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5744 * allocated value (e.g., a string). See bug issue
5745 * https://github.com/nlohmann/json/issues/2865 for more information.
5746 */
5747
5748template<value_t> struct external_constructor;
5749
5750template<>
5752{
5753 template<typename BasicJsonType>
5754 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5755 {
5756 j.m_data.m_value.destroy(j.m_data.m_type);
5757 j.m_data.m_type = value_t::boolean;
5758 j.m_data.m_value = b;
5759 j.assert_invariant();
5760 }
5761};
5762
5763template<>
5765{
5766 template<typename BasicJsonType>
5767 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5768 {
5769 j.m_data.m_value.destroy(j.m_data.m_type);
5770 j.m_data.m_type = value_t::string;
5771 j.m_data.m_value = s;
5772 j.assert_invariant();
5773 }
5774
5775 template<typename BasicJsonType>
5776 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5777 {
5778 j.m_data.m_value.destroy(j.m_data.m_type);
5779 j.m_data.m_type = value_t::string;
5780 j.m_data.m_value = std::move(s);
5781 j.assert_invariant();
5782 }
5783
5784 template < typename BasicJsonType, typename CompatibleStringType,
5785 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5786 int > = 0 >
5787 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5788 {
5789 j.m_data.m_value.destroy(j.m_data.m_type);
5790 j.m_data.m_type = value_t::string;
5791 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5792 j.assert_invariant();
5793 }
5794};
5795
5796template<>
5798{
5799 template<typename BasicJsonType>
5800 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5801 {
5802 j.m_data.m_value.destroy(j.m_data.m_type);
5803 j.m_data.m_type = value_t::binary;
5804 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5805 j.assert_invariant();
5806 }
5807
5808 template<typename BasicJsonType>
5809 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5810 {
5811 j.m_data.m_value.destroy(j.m_data.m_type);
5812 j.m_data.m_type = value_t::binary;
5813 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5814 j.assert_invariant();
5815 }
5816};
5817
5818template<>
5820{
5821 template<typename BasicJsonType>
5822 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5823 {
5824 j.m_data.m_value.destroy(j.m_data.m_type);
5825 j.m_data.m_type = value_t::number_float;
5826 j.m_data.m_value = val;
5827 j.assert_invariant();
5828 }
5829};
5830
5831template<>
5833{
5834 template<typename BasicJsonType>
5835 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5836 {
5837 j.m_data.m_value.destroy(j.m_data.m_type);
5838 j.m_data.m_type = value_t::number_unsigned;
5839 j.m_data.m_value = val;
5840 j.assert_invariant();
5841 }
5842};
5843
5844template<>
5846{
5847 template<typename BasicJsonType>
5848 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5849 {
5850 j.m_data.m_value.destroy(j.m_data.m_type);
5851 j.m_data.m_type = value_t::number_integer;
5852 j.m_data.m_value = val;
5853 j.assert_invariant();
5854 }
5855};
5856
5857template<>
5859{
5860 template<typename BasicJsonType>
5861 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5862 {
5863 j.m_data.m_value.destroy(j.m_data.m_type);
5864 j.m_data.m_type = value_t::array;
5865 j.m_data.m_value = arr;
5866 j.set_parents();
5867 j.assert_invariant();
5868 }
5869
5870 template<typename BasicJsonType>
5871 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5872 {
5873 j.m_data.m_value.destroy(j.m_data.m_type);
5874 j.m_data.m_type = value_t::array;
5875 j.m_data.m_value = std::move(arr);
5876 j.set_parents();
5877 j.assert_invariant();
5878 }
5879
5880 template < typename BasicJsonType, typename CompatibleArrayType,
5881 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5882 int > = 0 >
5883 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5884 {
5885 using std::begin;
5886 using std::end;
5887
5888 j.m_data.m_value.destroy(j.m_data.m_type);
5889 j.m_data.m_type = value_t::array;
5890 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5891 j.set_parents();
5892 j.assert_invariant();
5893 }
5894
5895 template<typename BasicJsonType>
5896 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5897 {
5898 j.m_data.m_value.destroy(j.m_data.m_type);
5899 j.m_data.m_type = value_t::array;
5900 j.m_data.m_value = value_t::array;
5901 j.m_data.m_value.array->reserve(arr.size());
5902 for (const bool x : arr)
5903 {
5904 j.m_data.m_value.array->push_back(x);
5905 j.set_parent(j.m_data.m_value.array->back());
5906 }
5907 j.assert_invariant();
5908 }
5909
5910 template<typename BasicJsonType, typename T,
5911 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5912 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5913 {
5914 j.m_data.m_value.destroy(j.m_data.m_type);
5915 j.m_data.m_type = value_t::array;
5916 j.m_data.m_value = value_t::array;
5917 j.m_data.m_value.array->resize(arr.size());
5918 if (arr.size() > 0)
5919 {
5920 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5921 }
5922 j.set_parents();
5923 j.assert_invariant();
5924 }
5925};
5926
5927template<>
5929{
5930 template<typename BasicJsonType>
5931 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5932 {
5933 j.m_data.m_value.destroy(j.m_data.m_type);
5934 j.m_data.m_type = value_t::object;
5935 j.m_data.m_value = obj;
5936 j.set_parents();
5937 j.assert_invariant();
5938 }
5939
5940 template<typename BasicJsonType>
5941 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5942 {
5943 j.m_data.m_value.destroy(j.m_data.m_type);
5944 j.m_data.m_type = value_t::object;
5945 j.m_data.m_value = std::move(obj);
5946 j.set_parents();
5947 j.assert_invariant();
5948 }
5949
5950 template < typename BasicJsonType, typename CompatibleObjectType,
5951 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5952 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5953 {
5954 using std::begin;
5955 using std::end;
5956
5957 j.m_data.m_value.destroy(j.m_data.m_type);
5958 j.m_data.m_type = value_t::object;
5959 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5960 j.set_parents();
5961 j.assert_invariant();
5962 }
5963};
5964
5966// to_json //
5968
5969#ifdef JSON_HAS_CPP_17
5970template<typename BasicJsonType, typename T,
5971 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5972void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5973{
5974 if (opt.has_value())
5975 {
5976 j = *opt;
5977 }
5978 else
5979 {
5980 j = nullptr;
5981 }
5982}
5983#endif
5984
5985template<typename BasicJsonType, typename T,
5986 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5987inline void to_json(BasicJsonType& j, T b) noexcept
5988{
5990}
5991
5992template < typename BasicJsonType, typename BoolRef,
5993 enable_if_t <
5994 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5995 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5996 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5997 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5998 typename BasicJsonType::boolean_t >::value))
5999 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
6000inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
6001{
6002 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
6003}
6004
6005template<typename BasicJsonType, typename CompatibleString,
6006 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
6007inline void to_json(BasicJsonType& j, const CompatibleString& s)
6008{
6010}
6011
6012template<typename BasicJsonType>
6013inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
6014{
6016}
6017
6018template<typename BasicJsonType, typename FloatType,
6019 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
6020inline void to_json(BasicJsonType& j, FloatType val) noexcept
6021{
6022 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6023}
6024
6025template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6026 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6027inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6028{
6029 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6030}
6031
6032template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6033 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6034inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6035{
6036 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6037}
6038
6039#if !JSON_DISABLE_ENUM_SERIALIZATION
6040template<typename BasicJsonType, typename EnumType,
6041 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6042inline void to_json(BasicJsonType& j, EnumType e) noexcept
6043{
6044 using underlying_type = typename std::underlying_type<EnumType>::type;
6045 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6046 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6047}
6048#endif // JSON_DISABLE_ENUM_SERIALIZATION
6049
6050template<typename BasicJsonType>
6051inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6052{
6054}
6055
6056template < typename BasicJsonType, typename CompatibleArrayType,
6057 enable_if_t < is_compatible_array_type<BasicJsonType,
6058 CompatibleArrayType>::value&&
6060 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
6061 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6063 int > = 0 >
6064inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6065{
6067}
6068
6069template<typename BasicJsonType>
6070inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6071{
6073}
6074
6075template<typename BasicJsonType, typename T,
6076 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6077inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6078{
6080}
6081
6082template<typename BasicJsonType>
6083inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6084{
6086}
6087
6088template < typename BasicJsonType, typename CompatibleObjectType,
6089 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6090inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6091{
6093}
6094
6095template<typename BasicJsonType>
6096inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6097{
6099}
6100
6101template <
6102 typename BasicJsonType, typename T, std::size_t N,
6103 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6104 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6105 int > = 0 >
6106inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6107{
6109}
6110
6111template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6112inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6113{
6114 j = { p.first, p.second };
6115}
6116
6117// for https://github.com/nlohmann/json/pull/1134
6118template<typename BasicJsonType, typename T,
6119 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
6120inline void to_json(BasicJsonType& j, const T& b)
6121{
6122 j = { {b.key(), b.value()} };
6123}
6124
6125template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6126inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6127{
6128 j = { std::get<Idx>(t)... };
6129}
6130
6131template<typename BasicJsonType, typename Tuple>
6132inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6133{
6134 using array_t = typename BasicJsonType::array_t;
6135 j = array_t();
6136}
6137
6138template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6139inline void to_json(BasicJsonType& j, const T& t)
6140{
6141 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6142}
6143
6144#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6145#if defined(__cpp_lib_char8_t)
6146template<typename BasicJsonType, typename Tr, typename Allocator>
6147inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6148{
6149 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6150 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6151}
6152#endif
6153
6154template<typename BasicJsonType>
6155inline void to_json(BasicJsonType& j, const std_fs::path& p)
6156{
6157 // Returns either a std::string or a std::u8string depending whether library
6158 // support for char8_t is enabled.
6159 j = p.u8string();
6160}
6161#endif
6162
6164{
6165 template<typename BasicJsonType, typename T>
6166 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6167 -> decltype(to_json(j, std::forward<T>(val)), void())
6168 {
6169 return to_json(j, std::forward<T>(val));
6170 }
6171};
6172} // namespace detail
6173
6174#ifndef JSON_HAS_CPP_17
6178namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6179{
6180#endif
6181JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6182 detail::static_const<detail::to_json_fn>::value;
6183#ifndef JSON_HAS_CPP_17
6184} // namespace
6185#endif
6186
6187NLOHMANN_JSON_NAMESPACE_END
6188
6189// #include <nlohmann/detail/meta/identity_tag.hpp>
6190
6191
6192NLOHMANN_JSON_NAMESPACE_BEGIN
6193
6195template<typename ValueType, typename>
6197{
6200 template<typename BasicJsonType, typename TargetType = ValueType>
6201 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6202 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6203 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6204 {
6205 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6206 }
6207
6210 template<typename BasicJsonType, typename TargetType = ValueType>
6211 static auto from_json(BasicJsonType && j) noexcept(
6212 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6213 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6214 {
6215 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6216 }
6217
6220 template<typename BasicJsonType, typename TargetType = ValueType>
6221 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6222 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6223 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6224 {
6225 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6226 }
6227};
6228
6229NLOHMANN_JSON_NAMESPACE_END
6230
6231// #include <nlohmann/byte_container_with_subtype.hpp>
6232// __ _____ _____ _____
6233// __| | __| | | | JSON for Modern C++
6234// | | |__ | | | | | | version 3.12.0
6235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6236//
6237// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
6238// SPDX-License-Identifier: MIT
6239
6240
6241
6242#include <cstdint> // uint8_t, uint64_t
6243#include <tuple> // tie
6244#include <utility> // move
6245
6246// #include <nlohmann/detail/abi_macros.hpp>
6247
6248
6249NLOHMANN_JSON_NAMESPACE_BEGIN
6250
6253template<typename BinaryType>
6254class byte_container_with_subtype : public BinaryType
6255{
6256 public:
6257 using container_type = BinaryType;
6258 using subtype_type = std::uint64_t;
6259
6261 byte_container_with_subtype() noexcept(noexcept(container_type()))
6262 : container_type()
6263 {}
6264
6266 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
6267 : container_type(b)
6268 {}
6269
6271 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6272 : container_type(std::move(b))
6273 {}
6274
6276 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
6277 : container_type(b)
6278 , m_subtype(subtype_)
6279 , m_has_subtype(true)
6280 {}
6281
6283 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6284 : container_type(std::move(b))
6285 , m_subtype(subtype_)
6286 , m_has_subtype(true)
6287 {}
6288
6289 bool operator==(const byte_container_with_subtype& rhs) const
6290 {
6291 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6292 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6293 }
6294
6295 bool operator!=(const byte_container_with_subtype& rhs) const
6296 {
6297 return !(rhs == *this);
6298 }
6299
6302 void set_subtype(subtype_type subtype_) noexcept
6303 {
6304 m_subtype = subtype_;
6305 m_has_subtype = true;
6306 }
6307
6310 constexpr subtype_type subtype() const noexcept
6311 {
6312 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6313 }
6314
6317 constexpr bool has_subtype() const noexcept
6318 {
6319 return m_has_subtype;
6320 }
6321
6324 void clear_subtype() noexcept
6325 {
6326 m_subtype = 0;
6327 m_has_subtype = false;
6328 }
6329
6330 private:
6331 subtype_type m_subtype = 0;
6332 bool m_has_subtype = false;
6333};
6334
6335NLOHMANN_JSON_NAMESPACE_END
6336
6337// #include <nlohmann/detail/conversions/from_json.hpp>
6338
6339// #include <nlohmann/detail/conversions/to_json.hpp>
6340
6341// #include <nlohmann/detail/exceptions.hpp>
6342
6343// #include <nlohmann/detail/hash.hpp>
6344// __ _____ _____ _____
6345// __| | __| | | | JSON for Modern C++
6346// | | |__ | | | | | | version 3.12.0
6347// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6348//
6349// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
6350// SPDX-License-Identifier: MIT
6351
6352
6353
6354#include <cstdint> // uint8_t
6355#include <cstddef> // size_t
6356#include <functional> // hash
6357
6358// #include <nlohmann/detail/abi_macros.hpp>
6359
6360// #include <nlohmann/detail/value_t.hpp>
6361
6362
6363NLOHMANN_JSON_NAMESPACE_BEGIN
6364namespace detail
6365{
6366
6367// boost::hash_combine
6368inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6369{
6370 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6371 return seed;
6372}
6373
6385template<typename BasicJsonType>
6386std::size_t hash(const BasicJsonType& j)
6387{
6388 using string_t = typename BasicJsonType::string_t;
6389 using number_integer_t = typename BasicJsonType::number_integer_t;
6390 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6391 using number_float_t = typename BasicJsonType::number_float_t;
6392
6393 const auto type = static_cast<std::size_t>(j.type());
6394 switch (j.type())
6395 {
6396 case BasicJsonType::value_t::null:
6397 case BasicJsonType::value_t::discarded:
6398 {
6399 return combine(type, 0);
6400 }
6401
6402 case BasicJsonType::value_t::object:
6403 {
6404 auto seed = combine(type, j.size());
6405 for (const auto& element : j.items())
6406 {
6407 const auto h = std::hash<string_t> {}(element.key());
6408 seed = combine(seed, h);
6409 seed = combine(seed, hash(element.value()));
6410 }
6411 return seed;
6412 }
6413
6414 case BasicJsonType::value_t::array:
6415 {
6416 auto seed = combine(type, j.size());
6417 for (const auto& element : j)
6418 {
6419 seed = combine(seed, hash(element));
6420 }
6421 return seed;
6422 }
6423
6424 case BasicJsonType::value_t::string:
6425 {
6426 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6427 return combine(type, h);
6428 }
6429
6430 case BasicJsonType::value_t::boolean:
6431 {
6432 const auto h = std::hash<bool> {}(j.template get<bool>());
6433 return combine(type, h);
6434 }
6435
6436 case BasicJsonType::value_t::number_integer:
6437 {
6438 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6439 return combine(type, h);
6440 }
6441
6442 case BasicJsonType::value_t::number_unsigned:
6443 {
6444 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6445 return combine(type, h);
6446 }
6447
6448 case BasicJsonType::value_t::number_float:
6449 {
6450 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6451 return combine(type, h);
6452 }
6453
6454 case BasicJsonType::value_t::binary:
6455 {
6456 auto seed = combine(type, j.get_binary().size());
6457 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6458 seed = combine(seed, h);
6459 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6460 for (const auto byte : j.get_binary())
6461 {
6462 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6463 }
6464 return seed;
6465 }
6466
6467 default: // LCOV_EXCL_LINE
6468 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6469 return 0; // LCOV_EXCL_LINE
6470 }
6471}
6472
6473} // namespace detail
6474NLOHMANN_JSON_NAMESPACE_END
6475
6476// #include <nlohmann/detail/input/binary_reader.hpp>
6477// __ _____ _____ _____
6478// __| | __| | | | JSON for Modern C++
6479// | | |__ | | | | | | version 3.12.0
6480// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6481//
6482// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
6483// SPDX-License-Identifier: MIT
6484
6485
6486
6487#include <algorithm> // generate_n
6488#include <array> // array
6489#include <cmath> // ldexp
6490#include <cstddef> // size_t
6491#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6492#include <cstdio> // snprintf
6493#include <cstring> // memcpy
6494#include <iterator> // back_inserter
6495#include <limits> // numeric_limits
6496#include <string> // char_traits, string
6497#include <utility> // make_pair, move
6498#include <vector> // vector
6499#ifdef __cpp_lib_byteswap
6500 #include <bit> //byteswap
6501#endif
6502
6503// #include <nlohmann/detail/exceptions.hpp>
6504
6505// #include <nlohmann/detail/input/input_adapters.hpp>
6506// __ _____ _____ _____
6507// __| | __| | | | JSON for Modern C++
6508// | | |__ | | | | | | version 3.12.0
6509// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6510//
6511// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
6512// SPDX-License-Identifier: MIT
6513
6514
6515
6516#include <array> // array
6517#include <cstddef> // size_t
6518#include <cstring> // strlen
6519#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6520#include <memory> // shared_ptr, make_shared, addressof
6521#include <numeric> // accumulate
6522#include <streambuf> // streambuf
6523#include <string> // string, char_traits
6524#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6525#include <utility> // pair, declval
6526
6527#ifndef JSON_NO_IO
6528 #include <cstdio> // FILE *
6529 #include <istream> // istream
6530#endif // JSON_NO_IO
6531
6532// #include <nlohmann/detail/exceptions.hpp>
6533
6534// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6535
6536// #include <nlohmann/detail/macro_scope.hpp>
6537
6538// #include <nlohmann/detail/meta/type_traits.hpp>
6539
6540
6541NLOHMANN_JSON_NAMESPACE_BEGIN
6542namespace detail
6543{
6544
6546enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6547
6549// input adapters //
6551
6552#ifndef JSON_NO_IO
6557class file_input_adapter
6558{
6559 public:
6560 using char_type = char;
6561
6562 JSON_HEDLEY_NON_NULL(2)
6563 explicit file_input_adapter(std::FILE* f) noexcept
6564 : m_file(f)
6565 {
6566 JSON_ASSERT(m_file != nullptr);
6567 }
6568
6569 // make class move-only
6570 file_input_adapter(const file_input_adapter&) = delete;
6571 file_input_adapter(file_input_adapter&&) noexcept = default;
6572 file_input_adapter& operator=(const file_input_adapter&) = delete;
6573 file_input_adapter& operator=(file_input_adapter&&) = delete;
6574 ~file_input_adapter() = default;
6575
6576 std::char_traits<char>::int_type get_character() noexcept
6577 {
6578 return std::fgetc(m_file);
6579 }
6580
6581 // returns the number of characters successfully read
6582 template<class T>
6583 std::size_t get_elements(T* dest, std::size_t count = 1)
6584 {
6585 return fread(dest, 1, sizeof(T) * count, m_file);
6586 }
6587
6588 private:
6590 std::FILE* m_file;
6591};
6592
6602class input_stream_adapter
6603{
6604 public:
6605 using char_type = char;
6606
6607 ~input_stream_adapter()
6608 {
6609 // clear stream flags; we use underlying streambuf I/O, do not
6610 // maintain ifstream flags, except eof
6611 if (is != nullptr)
6612 {
6613 is->clear(is->rdstate() & std::ios::eofbit);
6614 }
6615 }
6616
6617 explicit input_stream_adapter(std::istream& i)
6618 : is(&i), sb(i.rdbuf())
6619 {}
6620
6621 // deleted because of pointer members
6622 input_stream_adapter(const input_stream_adapter&) = delete;
6623 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6624 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6625
6626 input_stream_adapter(input_stream_adapter&& rhs) noexcept
6627 : is(rhs.is), sb(rhs.sb)
6628 {
6629 rhs.is = nullptr;
6630 rhs.sb = nullptr;
6631 }
6632
6633 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6634 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6635 // end up as the same value, e.g., 0xFFFFFFFF.
6636 std::char_traits<char>::int_type get_character()
6637 {
6638 auto res = sb->sbumpc();
6639 // set eof manually, as we don't use the istream interface.
6640 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6641 {
6642 is->clear(is->rdstate() | std::ios::eofbit);
6643 }
6644 return res;
6645 }
6646
6647 template<class T>
6648 std::size_t get_elements(T* dest, std::size_t count = 1)
6649 {
6650 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6651 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6652 {
6653 is->clear(is->rdstate() | std::ios::eofbit);
6654 }
6655 return res;
6656 }
6657
6658 private:
6660 std::istream* is = nullptr;
6661 std::streambuf* sb = nullptr;
6662};
6663#endif // JSON_NO_IO
6664
6665// General-purpose iterator-based adapter. It might not be as fast as
6666// theoretically possible for some containers, but it is extremely versatile.
6667template<typename IteratorType>
6668class iterator_input_adapter
6669{
6670 public:
6671 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6672
6673 iterator_input_adapter(IteratorType first, IteratorType last)
6674 : current(std::move(first)), end(std::move(last))
6675 {}
6676
6677 typename char_traits<char_type>::int_type get_character()
6678 {
6679 if (JSON_HEDLEY_LIKELY(current != end))
6680 {
6681 auto result = char_traits<char_type>::to_int_type(*current);
6682 std::advance(current, 1);
6683 return result;
6684 }
6685
6687 }
6688
6689 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6690 template<class T>
6691 std::size_t get_elements(T* dest, std::size_t count = 1)
6692 {
6693 auto* ptr = reinterpret_cast<char*>(dest);
6694 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6695 {
6696 if (JSON_HEDLEY_LIKELY(current != end))
6697 {
6698 ptr[read_index] = static_cast<char>(*current);
6699 std::advance(current, 1);
6700 }
6701 else
6702 {
6703 return read_index;
6704 }
6705 }
6706 return count * sizeof(T);
6707 }
6708
6709 private:
6710 IteratorType current;
6711 IteratorType end;
6712
6713 template<typename BaseInputAdapter, size_t T>
6714 friend struct wide_string_input_helper;
6715
6716 bool empty() const
6717 {
6718 return current == end;
6719 }
6720};
6721
6722template<typename BaseInputAdapter, size_t T>
6724
6725template<typename BaseInputAdapter>
6726struct wide_string_input_helper<BaseInputAdapter, 4>
6727{
6728 // UTF-32
6729 static void fill_buffer(BaseInputAdapter& input,
6730 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6731 size_t& utf8_bytes_index,
6732 size_t& utf8_bytes_filled)
6733 {
6734 utf8_bytes_index = 0;
6735
6736 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6737 {
6738 utf8_bytes[0] = std::char_traits<char>::eof();
6739 utf8_bytes_filled = 1;
6740 }
6741 else
6742 {
6743 // get the current character
6744 const auto wc = input.get_character();
6745
6746 // UTF-32 to UTF-8 encoding
6747 if (wc < 0x80)
6748 {
6749 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6750 utf8_bytes_filled = 1;
6751 }
6752 else if (wc <= 0x7FF)
6753 {
6754 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6755 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6756 utf8_bytes_filled = 2;
6757 }
6758 else if (wc <= 0xFFFF)
6759 {
6760 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6761 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6762 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6763 utf8_bytes_filled = 3;
6764 }
6765 else if (wc <= 0x10FFFF)
6766 {
6767 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6768 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6769 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6770 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6771 utf8_bytes_filled = 4;
6772 }
6773 else
6774 {
6775 // unknown character
6776 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6777 utf8_bytes_filled = 1;
6778 }
6779 }
6780 }
6781};
6782
6783template<typename BaseInputAdapter>
6784struct wide_string_input_helper<BaseInputAdapter, 2>
6785{
6786 // UTF-16
6787 static void fill_buffer(BaseInputAdapter& input,
6788 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6789 size_t& utf8_bytes_index,
6790 size_t& utf8_bytes_filled)
6791 {
6792 utf8_bytes_index = 0;
6793
6794 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6795 {
6796 utf8_bytes[0] = std::char_traits<char>::eof();
6797 utf8_bytes_filled = 1;
6798 }
6799 else
6800 {
6801 // get the current character
6802 const auto wc = input.get_character();
6803
6804 // UTF-16 to UTF-8 encoding
6805 if (wc < 0x80)
6806 {
6807 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6808 utf8_bytes_filled = 1;
6809 }
6810 else if (wc <= 0x7FF)
6811 {
6812 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6813 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6814 utf8_bytes_filled = 2;
6815 }
6816 else if (0xD800 > wc || wc >= 0xE000)
6817 {
6818 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6819 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6820 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6821 utf8_bytes_filled = 3;
6822 }
6823 else
6824 {
6825 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6826 {
6827 const auto wc2 = static_cast<unsigned int>(input.get_character());
6828 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6829 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6830 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6831 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6832 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6833 utf8_bytes_filled = 4;
6834 }
6835 else
6836 {
6837 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6838 utf8_bytes_filled = 1;
6839 }
6840 }
6841 }
6842 }
6843};
6844
6845// Wraps another input adapter to convert wide character types into individual bytes.
6846template<typename BaseInputAdapter, typename WideCharType>
6847class wide_string_input_adapter
6848{
6849 public:
6850 using char_type = char;
6851
6852 wide_string_input_adapter(BaseInputAdapter base)
6853 : base_adapter(base) {}
6854
6855 typename std::char_traits<char>::int_type get_character() noexcept
6856 {
6857 // check if the buffer needs to be filled
6858 if (utf8_bytes_index == utf8_bytes_filled)
6859 {
6860 fill_buffer<sizeof(WideCharType)>();
6861
6862 JSON_ASSERT(utf8_bytes_filled > 0);
6863 JSON_ASSERT(utf8_bytes_index == 0);
6864 }
6865
6866 // use buffer
6867 JSON_ASSERT(utf8_bytes_filled > 0);
6868 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6869 return utf8_bytes[utf8_bytes_index++];
6870 }
6871
6872 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6873 template<class T>
6874 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6875 {
6876 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6877 }
6878
6879 private:
6880 BaseInputAdapter base_adapter;
6881
6882 template<size_t T>
6883 void fill_buffer()
6884 {
6885 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6886 }
6887
6889 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6890
6892 std::size_t utf8_bytes_index = 0;
6894 std::size_t utf8_bytes_filled = 0;
6895};
6896
6897template<typename IteratorType, typename Enable = void>
6899{
6900 using iterator_type = IteratorType;
6901 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6902 using adapter_type = iterator_input_adapter<iterator_type>;
6903
6904 static adapter_type create(IteratorType first, IteratorType last)
6905 {
6906 return adapter_type(std::move(first), std::move(last));
6907 }
6908};
6909
6910template<typename T>
6912{
6913 using value_type = typename std::iterator_traits<T>::value_type;
6914 enum // NOLINT(cppcoreguidelines-use-enum-class)
6915 {
6916 value = sizeof(value_type) > 1
6917 };
6918};
6919
6920template<typename IteratorType>
6921struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6922{
6923 using iterator_type = IteratorType;
6924 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6925 using base_adapter_type = iterator_input_adapter<iterator_type>;
6927
6928 static adapter_type create(IteratorType first, IteratorType last)
6929 {
6930 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6931 }
6932};
6933
6934// General purpose iterator-based input
6935template<typename IteratorType>
6936typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6937{
6939 return factory_type::create(first, last);
6940}
6941
6942// Convenience shorthand from container to iterator
6943// Enables ADL on begin(container) and end(container)
6944// Encloses the using declarations in namespace for not to leak them to outside scope
6945
6946namespace container_input_adapter_factory_impl
6947{
6948
6949using std::begin;
6950using std::end;
6951
6952template<typename ContainerType, typename Enable = void>
6954
6955template<typename ContainerType>
6957 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6958 {
6959 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6960
6961 static adapter_type create(const ContainerType& container)
6962{
6963 return input_adapter(begin(container), end(container));
6964}
6965 };
6966
6967} // namespace container_input_adapter_factory_impl
6968
6969template<typename ContainerType>
6971{
6973}
6974
6975// specialization for std::string
6976using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6977
6978#ifndef JSON_NO_IO
6979// Special cases with fast paths
6980inline file_input_adapter input_adapter(std::FILE* file)
6981{
6982 if (file == nullptr)
6983 {
6984 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));
6985 }
6986 return file_input_adapter(file);
6987}
6988
6989inline input_stream_adapter input_adapter(std::istream& stream)
6990{
6991 return input_stream_adapter(stream);
6992}
6993
6994inline input_stream_adapter input_adapter(std::istream&& stream)
6995{
6996 return input_stream_adapter(stream);
6997}
6998#endif // JSON_NO_IO
6999
7000using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
7001
7002// Null-delimited strings, and the like.
7003template < typename CharT,
7004 typename std::enable_if <
7005 std::is_pointer<CharT>::value&&
7006 !std::is_array<CharT>::value&&
7007 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7008 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7009 int >::type = 0 >
7010contiguous_bytes_input_adapter input_adapter(CharT b)
7011{
7012 if (b == nullptr)
7013 {
7014 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));
7015 }
7016 auto length = std::strlen(reinterpret_cast<const char*>(b));
7017 const auto* ptr = reinterpret_cast<const char*>(b);
7018 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
7019}
7020
7021template<typename T, std::size_t N>
7022auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7023{
7024 return input_adapter(array, array + N);
7025}
7026
7027// This class only handles inputs of input_buffer_adapter type.
7028// It's required so that expressions like {ptr, len} can be implicitly cast
7029// to the correct adapter.
7030class span_input_adapter
7031{
7032 public:
7033 template < typename CharT,
7034 typename std::enable_if <
7035 std::is_pointer<CharT>::value&&
7036 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7037 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7038 int >::type = 0 >
7039 span_input_adapter(CharT b, std::size_t l)
7040 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7041
7042 template<class IteratorType,
7043 typename std::enable_if<
7044 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7045 int>::type = 0>
7046 span_input_adapter(IteratorType first, IteratorType last)
7047 : ia(input_adapter(first, last)) {}
7048
7049 contiguous_bytes_input_adapter&& get()
7050 {
7051 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7052 }
7053
7054 private:
7055 contiguous_bytes_input_adapter ia;
7056};
7057
7058} // namespace detail
7059NLOHMANN_JSON_NAMESPACE_END
7060
7061// #include <nlohmann/detail/input/json_sax.hpp>
7062// __ _____ _____ _____
7063// __| | __| | | | JSON for Modern C++
7064// | | |__ | | | | | | version 3.12.0
7065// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7066//
7067// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
7068// SPDX-License-Identifier: MIT
7069
7070
7071
7072#include <cstddef>
7073#include <string> // string
7074#include <type_traits> // enable_if_t
7075#include <utility> // move
7076#include <vector> // vector
7077
7078// #include <nlohmann/detail/exceptions.hpp>
7079
7080// #include <nlohmann/detail/input/lexer.hpp>
7081// __ _____ _____ _____
7082// __| | __| | | | JSON for Modern C++
7083// | | |__ | | | | | | version 3.12.0
7084// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7085//
7086// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
7087// SPDX-License-Identifier: MIT
7088
7089
7090
7091#include <array> // array
7092#include <clocale> // localeconv
7093#include <cstddef> // size_t
7094#include <cstdio> // snprintf
7095#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7096#include <initializer_list> // initializer_list
7097#include <string> // char_traits, string
7098#include <utility> // move
7099#include <vector> // vector
7100
7101// #include <nlohmann/detail/input/input_adapters.hpp>
7102
7103// #include <nlohmann/detail/input/position_t.hpp>
7104
7105// #include <nlohmann/detail/macro_scope.hpp>
7106
7107// #include <nlohmann/detail/meta/type_traits.hpp>
7108
7109
7110NLOHMANN_JSON_NAMESPACE_BEGIN
7111namespace detail
7112{
7113
7115// lexer //
7117
7118template<typename BasicJsonType>
7120{
7121 public:
7143
7145 JSON_HEDLEY_RETURNS_NON_NULL
7146 JSON_HEDLEY_CONST
7147 static const char* token_type_name(const token_type t) noexcept
7148 {
7149 switch (t)
7150 {
7152 return "<uninitialized>";
7154 return "true literal";
7156 return "false literal";
7158 return "null literal";
7160 return "string literal";
7164 return "number literal";
7166 return "'['";
7168 return "'{'";
7170 return "']'";
7172 return "'}'";
7174 return "':'";
7176 return "','";
7178 return "<parse error>";
7180 return "end of input";
7182 return "'[', '{', or a literal";
7183 // LCOV_EXCL_START
7184 default: // catch non-enum values
7185 return "unknown token";
7186 // LCOV_EXCL_STOP
7187 }
7188 }
7189};
7190
7195template<typename BasicJsonType, typename InputAdapterType>
7196class lexer : public lexer_base<BasicJsonType>
7197{
7198 using number_integer_t = typename BasicJsonType::number_integer_t;
7199 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7200 using number_float_t = typename BasicJsonType::number_float_t;
7201 using string_t = typename BasicJsonType::string_t;
7202 using char_type = typename InputAdapterType::char_type;
7203 using char_int_type = typename char_traits<char_type>::int_type;
7204
7205 public:
7206 using token_type = typename lexer_base<BasicJsonType>::token_type;
7207
7208 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7209 : ia(std::move(adapter))
7210 , ignore_comments(ignore_comments_)
7211 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7212 {}
7213
7214 // deleted because of pointer members
7215 lexer(const lexer&) = delete;
7216 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7217 lexer& operator=(lexer&) = delete;
7218 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7219 ~lexer() = default;
7220
7221 private:
7223 // locales
7225
7227 JSON_HEDLEY_PURE
7228 static char get_decimal_point() noexcept
7229 {
7230 const auto* loc = localeconv();
7231 JSON_ASSERT(loc != nullptr);
7232 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7233 }
7234
7236 // scan functions
7238
7254 int get_codepoint()
7255 {
7256 // this function only makes sense after reading `\u`
7257 JSON_ASSERT(current == 'u');
7258 int codepoint = 0;
7259
7260 const auto factors = { 12u, 8u, 4u, 0u };
7261 for (const auto factor : factors)
7262 {
7263 get();
7264
7265 if (current >= '0' && current <= '9')
7266 {
7267 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7268 }
7269 else if (current >= 'A' && current <= 'F')
7270 {
7271 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7272 }
7273 else if (current >= 'a' && current <= 'f')
7274 {
7275 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7276 }
7277 else
7278 {
7279 return -1;
7280 }
7281 }
7282
7283 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7284 return codepoint;
7285 }
7286
7302 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7303 {
7304 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7305 add(current);
7306
7307 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7308 {
7309 get();
7310 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7311 {
7312 add(current);
7313 }
7314 else
7315 {
7316 error_message = "invalid string: ill-formed UTF-8 byte";
7317 return false;
7318 }
7319 }
7320
7321 return true;
7322 }
7323
7339 token_type scan_string()
7340 {
7341 // reset token_buffer (ignore opening quote)
7342 reset();
7343
7344 // we entered the function by reading an open quote
7345 JSON_ASSERT(current == '\"');
7346
7347 while (true)
7348 {
7349 // get the next character
7350 switch (get())
7351 {
7352 // end of file while parsing the string
7354 {
7355 error_message = "invalid string: missing closing quote";
7356 return token_type::parse_error;
7357 }
7358
7359 // closing quote
7360 case '\"':
7361 {
7362 return token_type::value_string;
7363 }
7364
7365 // escapes
7366 case '\\':
7367 {
7368 switch (get())
7369 {
7370 // quotation mark
7371 case '\"':
7372 add('\"');
7373 break;
7374 // reverse solidus
7375 case '\\':
7376 add('\\');
7377 break;
7378 // solidus
7379 case '/':
7380 add('/');
7381 break;
7382 // backspace
7383 case 'b':
7384 add('\b');
7385 break;
7386 // form feed
7387 case 'f':
7388 add('\f');
7389 break;
7390 // line feed
7391 case 'n':
7392 add('\n');
7393 break;
7394 // carriage return
7395 case 'r':
7396 add('\r');
7397 break;
7398 // tab
7399 case 't':
7400 add('\t');
7401 break;
7402
7403 // unicode escapes
7404 case 'u':
7405 {
7406 const int codepoint1 = get_codepoint();
7407 int codepoint = codepoint1; // start with codepoint1
7408
7409 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7410 {
7411 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7412 return token_type::parse_error;
7413 }
7414
7415 // check if code point is a high surrogate
7416 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7417 {
7418 // expect next \uxxxx entry
7419 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7420 {
7421 const int codepoint2 = get_codepoint();
7422
7423 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7424 {
7425 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7426 return token_type::parse_error;
7427 }
7428
7429 // check if codepoint2 is a low surrogate
7430 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7431 {
7432 // overwrite codepoint
7433 codepoint = static_cast<int>(
7434 // high surrogate occupies the most significant 22 bits
7435 (static_cast<unsigned int>(codepoint1) << 10u)
7436 // low surrogate occupies the least significant 15 bits
7437 + static_cast<unsigned int>(codepoint2)
7438 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7439 // in the result, so we have to subtract with:
7440 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7441 - 0x35FDC00u);
7442 }
7443 else
7444 {
7445 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7446 return token_type::parse_error;
7447 }
7448 }
7449 else
7450 {
7451 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7452 return token_type::parse_error;
7453 }
7454 }
7455 else
7456 {
7457 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7458 {
7459 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7460 return token_type::parse_error;
7461 }
7462 }
7463
7464 // the result of the above calculation yields a proper codepoint
7465 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7466
7467 // translate codepoint into bytes
7468 if (codepoint < 0x80)
7469 {
7470 // 1-byte characters: 0xxxxxxx (ASCII)
7471 add(static_cast<char_int_type>(codepoint));
7472 }
7473 else if (codepoint <= 0x7FF)
7474 {
7475 // 2-byte characters: 110xxxxx 10xxxxxx
7476 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7477 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7478 }
7479 else if (codepoint <= 0xFFFF)
7480 {
7481 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7482 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7483 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7484 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7485 }
7486 else
7487 {
7488 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7489 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7490 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7491 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7492 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7493 }
7494
7495 break;
7496 }
7497
7498 // other characters after escape
7499 default:
7500 error_message = "invalid string: forbidden character after backslash";
7501 return token_type::parse_error;
7502 }
7503
7504 break;
7505 }
7506
7507 // invalid control characters
7508 case 0x00:
7509 {
7510 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7511 return token_type::parse_error;
7512 }
7513
7514 case 0x01:
7515 {
7516 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7517 return token_type::parse_error;
7518 }
7519
7520 case 0x02:
7521 {
7522 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7523 return token_type::parse_error;
7524 }
7525
7526 case 0x03:
7527 {
7528 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7529 return token_type::parse_error;
7530 }
7531
7532 case 0x04:
7533 {
7534 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7535 return token_type::parse_error;
7536 }
7537
7538 case 0x05:
7539 {
7540 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7541 return token_type::parse_error;
7542 }
7543
7544 case 0x06:
7545 {
7546 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7547 return token_type::parse_error;
7548 }
7549
7550 case 0x07:
7551 {
7552 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7553 return token_type::parse_error;
7554 }
7555
7556 case 0x08:
7557 {
7558 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7559 return token_type::parse_error;
7560 }
7561
7562 case 0x09:
7563 {
7564 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7565 return token_type::parse_error;
7566 }
7567
7568 case 0x0A:
7569 {
7570 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7571 return token_type::parse_error;
7572 }
7573
7574 case 0x0B:
7575 {
7576 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7577 return token_type::parse_error;
7578 }
7579
7580 case 0x0C:
7581 {
7582 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7583 return token_type::parse_error;
7584 }
7585
7586 case 0x0D:
7587 {
7588 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7589 return token_type::parse_error;
7590 }
7591
7592 case 0x0E:
7593 {
7594 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7595 return token_type::parse_error;
7596 }
7597
7598 case 0x0F:
7599 {
7600 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7601 return token_type::parse_error;
7602 }
7603
7604 case 0x10:
7605 {
7606 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7607 return token_type::parse_error;
7608 }
7609
7610 case 0x11:
7611 {
7612 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7613 return token_type::parse_error;
7614 }
7615
7616 case 0x12:
7617 {
7618 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7619 return token_type::parse_error;
7620 }
7621
7622 case 0x13:
7623 {
7624 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7625 return token_type::parse_error;
7626 }
7627
7628 case 0x14:
7629 {
7630 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7631 return token_type::parse_error;
7632 }
7633
7634 case 0x15:
7635 {
7636 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7637 return token_type::parse_error;
7638 }
7639
7640 case 0x16:
7641 {
7642 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7643 return token_type::parse_error;
7644 }
7645
7646 case 0x17:
7647 {
7648 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7649 return token_type::parse_error;
7650 }
7651
7652 case 0x18:
7653 {
7654 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7655 return token_type::parse_error;
7656 }
7657
7658 case 0x19:
7659 {
7660 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7661 return token_type::parse_error;
7662 }
7663
7664 case 0x1A:
7665 {
7666 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7667 return token_type::parse_error;
7668 }
7669
7670 case 0x1B:
7671 {
7672 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7673 return token_type::parse_error;
7674 }
7675
7676 case 0x1C:
7677 {
7678 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7679 return token_type::parse_error;
7680 }
7681
7682 case 0x1D:
7683 {
7684 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7685 return token_type::parse_error;
7686 }
7687
7688 case 0x1E:
7689 {
7690 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7691 return token_type::parse_error;
7692 }
7693
7694 case 0x1F:
7695 {
7696 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7697 return token_type::parse_error;
7698 }
7699
7700 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7701 case 0x20:
7702 case 0x21:
7703 case 0x23:
7704 case 0x24:
7705 case 0x25:
7706 case 0x26:
7707 case 0x27:
7708 case 0x28:
7709 case 0x29:
7710 case 0x2A:
7711 case 0x2B:
7712 case 0x2C:
7713 case 0x2D:
7714 case 0x2E:
7715 case 0x2F:
7716 case 0x30:
7717 case 0x31:
7718 case 0x32:
7719 case 0x33:
7720 case 0x34:
7721 case 0x35:
7722 case 0x36:
7723 case 0x37:
7724 case 0x38:
7725 case 0x39:
7726 case 0x3A:
7727 case 0x3B:
7728 case 0x3C:
7729 case 0x3D:
7730 case 0x3E:
7731 case 0x3F:
7732 case 0x40:
7733 case 0x41:
7734 case 0x42:
7735 case 0x43:
7736 case 0x44:
7737 case 0x45:
7738 case 0x46:
7739 case 0x47:
7740 case 0x48:
7741 case 0x49:
7742 case 0x4A:
7743 case 0x4B:
7744 case 0x4C:
7745 case 0x4D:
7746 case 0x4E:
7747 case 0x4F:
7748 case 0x50:
7749 case 0x51:
7750 case 0x52:
7751 case 0x53:
7752 case 0x54:
7753 case 0x55:
7754 case 0x56:
7755 case 0x57:
7756 case 0x58:
7757 case 0x59:
7758 case 0x5A:
7759 case 0x5B:
7760 case 0x5D:
7761 case 0x5E:
7762 case 0x5F:
7763 case 0x60:
7764 case 0x61:
7765 case 0x62:
7766 case 0x63:
7767 case 0x64:
7768 case 0x65:
7769 case 0x66:
7770 case 0x67:
7771 case 0x68:
7772 case 0x69:
7773 case 0x6A:
7774 case 0x6B:
7775 case 0x6C:
7776 case 0x6D:
7777 case 0x6E:
7778 case 0x6F:
7779 case 0x70:
7780 case 0x71:
7781 case 0x72:
7782 case 0x73:
7783 case 0x74:
7784 case 0x75:
7785 case 0x76:
7786 case 0x77:
7787 case 0x78:
7788 case 0x79:
7789 case 0x7A:
7790 case 0x7B:
7791 case 0x7C:
7792 case 0x7D:
7793 case 0x7E:
7794 case 0x7F:
7795 {
7796 add(current);
7797 break;
7798 }
7799
7800 // U+0080..U+07FF: bytes C2..DF 80..BF
7801 case 0xC2:
7802 case 0xC3:
7803 case 0xC4:
7804 case 0xC5:
7805 case 0xC6:
7806 case 0xC7:
7807 case 0xC8:
7808 case 0xC9:
7809 case 0xCA:
7810 case 0xCB:
7811 case 0xCC:
7812 case 0xCD:
7813 case 0xCE:
7814 case 0xCF:
7815 case 0xD0:
7816 case 0xD1:
7817 case 0xD2:
7818 case 0xD3:
7819 case 0xD4:
7820 case 0xD5:
7821 case 0xD6:
7822 case 0xD7:
7823 case 0xD8:
7824 case 0xD9:
7825 case 0xDA:
7826 case 0xDB:
7827 case 0xDC:
7828 case 0xDD:
7829 case 0xDE:
7830 case 0xDF:
7831 {
7832 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7833 {
7834 return token_type::parse_error;
7835 }
7836 break;
7837 }
7838
7839 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7840 case 0xE0:
7841 {
7842 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7843 {
7844 return token_type::parse_error;
7845 }
7846 break;
7847 }
7848
7849 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7850 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7851 case 0xE1:
7852 case 0xE2:
7853 case 0xE3:
7854 case 0xE4:
7855 case 0xE5:
7856 case 0xE6:
7857 case 0xE7:
7858 case 0xE8:
7859 case 0xE9:
7860 case 0xEA:
7861 case 0xEB:
7862 case 0xEC:
7863 case 0xEE:
7864 case 0xEF:
7865 {
7866 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7867 {
7868 return token_type::parse_error;
7869 }
7870 break;
7871 }
7872
7873 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7874 case 0xED:
7875 {
7876 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7877 {
7878 return token_type::parse_error;
7879 }
7880 break;
7881 }
7882
7883 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7884 case 0xF0:
7885 {
7886 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7887 {
7888 return token_type::parse_error;
7889 }
7890 break;
7891 }
7892
7893 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7894 case 0xF1:
7895 case 0xF2:
7896 case 0xF3:
7897 {
7898 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7899 {
7900 return token_type::parse_error;
7901 }
7902 break;
7903 }
7904
7905 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7906 case 0xF4:
7907 {
7908 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7909 {
7910 return token_type::parse_error;
7911 }
7912 break;
7913 }
7914
7915 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7916 default:
7917 {
7918 error_message = "invalid string: ill-formed UTF-8 byte";
7919 return token_type::parse_error;
7920 }
7921 }
7922 }
7923 }
7924
7929 bool scan_comment()
7930 {
7931 switch (get())
7932 {
7933 // single-line comments skip input until a newline or EOF is read
7934 case '/':
7935 {
7936 while (true)
7937 {
7938 switch (get())
7939 {
7940 case '\n':
7941 case '\r':
7943 case '\0':
7944 return true;
7945
7946 default:
7947 break;
7948 }
7949 }
7950 }
7951
7952 // multi-line comments skip input until */ is read
7953 case '*':
7954 {
7955 while (true)
7956 {
7957 switch (get())
7958 {
7960 case '\0':
7961 {
7962 error_message = "invalid comment; missing closing '*/'";
7963 return false;
7964 }
7965
7966 case '*':
7967 {
7968 switch (get())
7969 {
7970 case '/':
7971 return true;
7972
7973 default:
7974 {
7975 unget();
7976 continue;
7977 }
7978 }
7979 }
7980
7981 default:
7982 continue;
7983 }
7984 }
7985 }
7986
7987 // unexpected character after reading '/'
7988 default:
7989 {
7990 error_message = "invalid comment; expecting '/' or '*' after '/'";
7991 return false;
7992 }
7993 }
7994 }
7995
7996 JSON_HEDLEY_NON_NULL(2)
7997 static void strtof(float& f, const char* str, char** endptr) noexcept
7998 {
7999 f = std::strtof(str, endptr);
8000 }
8001
8002 JSON_HEDLEY_NON_NULL(2)
8003 static void strtof(double& f, const char* str, char** endptr) noexcept
8004 {
8005 f = std::strtod(str, endptr);
8006 }
8007
8008 JSON_HEDLEY_NON_NULL(2)
8009 static void strtof(long double& f, const char* str, char** endptr) noexcept
8010 {
8011 f = std::strtold(str, endptr);
8012 }
8013
8054 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.
8055 {
8056 // reset token_buffer to store the number's bytes
8057 reset();
8058
8059 // the type of the parsed number; initially set to unsigned; will be
8060 // changed if minus sign, decimal point, or exponent is read
8061 token_type number_type = token_type::value_unsigned;
8062
8063 // state (init): we just found out we need to scan a number
8064 switch (current)
8065 {
8066 case '-':
8067 {
8068 add(current);
8069 goto scan_number_minus;
8070 }
8071
8072 case '0':
8073 {
8074 add(current);
8075 goto scan_number_zero;
8076 }
8077
8078 case '1':
8079 case '2':
8080 case '3':
8081 case '4':
8082 case '5':
8083 case '6':
8084 case '7':
8085 case '8':
8086 case '9':
8087 {
8088 add(current);
8089 goto scan_number_any1;
8090 }
8091
8092 // all other characters are rejected outside scan_number()
8093 default: // LCOV_EXCL_LINE
8094 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8095 }
8096
8097scan_number_minus:
8098 // state: we just parsed a leading minus sign
8099 number_type = token_type::value_integer;
8100 switch (get())
8101 {
8102 case '0':
8103 {
8104 add(current);
8105 goto scan_number_zero;
8106 }
8107
8108 case '1':
8109 case '2':
8110 case '3':
8111 case '4':
8112 case '5':
8113 case '6':
8114 case '7':
8115 case '8':
8116 case '9':
8117 {
8118 add(current);
8119 goto scan_number_any1;
8120 }
8121
8122 default:
8123 {
8124 error_message = "invalid number; expected digit after '-'";
8125 return token_type::parse_error;
8126 }
8127 }
8128
8129scan_number_zero:
8130 // state: we just parse a zero (maybe with a leading minus sign)
8131 switch (get())
8132 {
8133 case '.':
8134 {
8135 add(decimal_point_char);
8136 decimal_point_position = token_buffer.size() - 1;
8137 goto scan_number_decimal1;
8138 }
8139
8140 case 'e':
8141 case 'E':
8142 {
8143 add(current);
8144 goto scan_number_exponent;
8145 }
8146
8147 default:
8148 goto scan_number_done;
8149 }
8150
8151scan_number_any1:
8152 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8153 switch (get())
8154 {
8155 case '0':
8156 case '1':
8157 case '2':
8158 case '3':
8159 case '4':
8160 case '5':
8161 case '6':
8162 case '7':
8163 case '8':
8164 case '9':
8165 {
8166 add(current);
8167 goto scan_number_any1;
8168 }
8169
8170 case '.':
8171 {
8172 add(decimal_point_char);
8173 decimal_point_position = token_buffer.size() - 1;
8174 goto scan_number_decimal1;
8175 }
8176
8177 case 'e':
8178 case 'E':
8179 {
8180 add(current);
8181 goto scan_number_exponent;
8182 }
8183
8184 default:
8185 goto scan_number_done;
8186 }
8187
8188scan_number_decimal1:
8189 // state: we just parsed a decimal point
8190 number_type = token_type::value_float;
8191 switch (get())
8192 {
8193 case '0':
8194 case '1':
8195 case '2':
8196 case '3':
8197 case '4':
8198 case '5':
8199 case '6':
8200 case '7':
8201 case '8':
8202 case '9':
8203 {
8204 add(current);
8205 goto scan_number_decimal2;
8206 }
8207
8208 default:
8209 {
8210 error_message = "invalid number; expected digit after '.'";
8211 return token_type::parse_error;
8212 }
8213 }
8214
8215scan_number_decimal2:
8216 // we just parsed at least one number after a decimal point
8217 switch (get())
8218 {
8219 case '0':
8220 case '1':
8221 case '2':
8222 case '3':
8223 case '4':
8224 case '5':
8225 case '6':
8226 case '7':
8227 case '8':
8228 case '9':
8229 {
8230 add(current);
8231 goto scan_number_decimal2;
8232 }
8233
8234 case 'e':
8235 case 'E':
8236 {
8237 add(current);
8238 goto scan_number_exponent;
8239 }
8240
8241 default:
8242 goto scan_number_done;
8243 }
8244
8245scan_number_exponent:
8246 // we just parsed an exponent
8247 number_type = token_type::value_float;
8248 switch (get())
8249 {
8250 case '+':
8251 case '-':
8252 {
8253 add(current);
8254 goto scan_number_sign;
8255 }
8256
8257 case '0':
8258 case '1':
8259 case '2':
8260 case '3':
8261 case '4':
8262 case '5':
8263 case '6':
8264 case '7':
8265 case '8':
8266 case '9':
8267 {
8268 add(current);
8269 goto scan_number_any2;
8270 }
8271
8272 default:
8273 {
8274 error_message =
8275 "invalid number; expected '+', '-', or digit after exponent";
8276 return token_type::parse_error;
8277 }
8278 }
8279
8280scan_number_sign:
8281 // we just parsed an exponent sign
8282 switch (get())
8283 {
8284 case '0':
8285 case '1':
8286 case '2':
8287 case '3':
8288 case '4':
8289 case '5':
8290 case '6':
8291 case '7':
8292 case '8':
8293 case '9':
8294 {
8295 add(current);
8296 goto scan_number_any2;
8297 }
8298
8299 default:
8300 {
8301 error_message = "invalid number; expected digit after exponent sign";
8302 return token_type::parse_error;
8303 }
8304 }
8305
8306scan_number_any2:
8307 // we just parsed a number after the exponent or exponent sign
8308 switch (get())
8309 {
8310 case '0':
8311 case '1':
8312 case '2':
8313 case '3':
8314 case '4':
8315 case '5':
8316 case '6':
8317 case '7':
8318 case '8':
8319 case '9':
8320 {
8321 add(current);
8322 goto scan_number_any2;
8323 }
8324
8325 default:
8326 goto scan_number_done;
8327 }
8328
8329scan_number_done:
8330 // unget the character after the number (we only read it to know that
8331 // we are done scanning a number)
8332 unget();
8333
8334 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8335 errno = 0;
8336
8337 // try to parse integers first and fall back to floats
8338 if (number_type == token_type::value_unsigned)
8339 {
8340 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8341
8342 // we checked the number format before
8343 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8344
8345 if (errno != ERANGE)
8346 {
8347 value_unsigned = static_cast<number_unsigned_t>(x);
8348 if (value_unsigned == x)
8349 {
8350 return token_type::value_unsigned;
8351 }
8352 }
8353 }
8354 else if (number_type == token_type::value_integer)
8355 {
8356 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8357
8358 // we checked the number format before
8359 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8360
8361 if (errno != ERANGE)
8362 {
8363 value_integer = static_cast<number_integer_t>(x);
8364 if (value_integer == x)
8365 {
8366 return token_type::value_integer;
8367 }
8368 }
8369 }
8370
8371 // this code is reached if we parse a floating-point number or if an
8372 // integer conversion above failed
8373 strtof(value_float, token_buffer.data(), &endptr);
8374
8375 // we checked the number format before
8376 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8377
8378 return token_type::value_float;
8379 }
8380
8386 JSON_HEDLEY_NON_NULL(2)
8387 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8388 token_type return_type)
8389 {
8390 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8391 for (std::size_t i = 1; i < length; ++i)
8392 {
8393 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8394 {
8395 error_message = "invalid literal";
8396 return token_type::parse_error;
8397 }
8398 }
8399 return return_type;
8400 }
8401
8403 // input management
8405
8407 void reset() noexcept
8408 {
8409 token_buffer.clear();
8410 token_string.clear();
8411 decimal_point_position = std::string::npos;
8412 token_string.push_back(char_traits<char_type>::to_char_type(current));
8413 }
8414
8415 /*
8416 @brief get next character from the input
8417
8418 This function provides the interface to the used input adapter. It does
8419 not throw in case the input reached EOF, but returns a
8420 `char_traits<char>::eof()` in that case. Stores the scanned characters
8421 for use in error messages.
8422
8423 @return character read from the input
8424 */
8425 char_int_type get()
8426 {
8427 ++position.chars_read_total;
8428 ++position.chars_read_current_line;
8429
8430 if (next_unget)
8431 {
8432 // only reset the next_unget variable and work with current
8433 next_unget = false;
8434 }
8435 else
8436 {
8437 current = ia.get_character();
8438 }
8439
8440 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8441 {
8442 token_string.push_back(char_traits<char_type>::to_char_type(current));
8443 }
8444
8445 if (current == '\n')
8446 {
8447 ++position.lines_read;
8448 position.chars_read_current_line = 0;
8449 }
8450
8451 return current;
8452 }
8453
8462 void unget()
8463 {
8464 next_unget = true;
8465
8466 --position.chars_read_total;
8467
8468 // in case we "unget" a newline, we have to also decrement the lines_read
8469 if (position.chars_read_current_line == 0)
8470 {
8471 if (position.lines_read > 0)
8472 {
8473 --position.lines_read;
8474 }
8475 }
8476 else
8477 {
8478 --position.chars_read_current_line;
8479 }
8480
8481 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8482 {
8483 JSON_ASSERT(!token_string.empty());
8484 token_string.pop_back();
8485 }
8486 }
8487
8489 void add(char_int_type c)
8490 {
8491 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8492 }
8493
8494 public:
8496 // value getters
8498
8500 constexpr number_integer_t get_number_integer() const noexcept
8501 {
8502 return value_integer;
8503 }
8504
8506 constexpr number_unsigned_t get_number_unsigned() const noexcept
8507 {
8508 return value_unsigned;
8509 }
8510
8512 constexpr number_float_t get_number_float() const noexcept
8513 {
8514 return value_float;
8515 }
8516
8518 string_t& get_string()
8519 {
8520 // translate decimal points from locale back to '.' (#4084)
8521 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8522 {
8523 token_buffer[decimal_point_position] = '.';
8524 }
8525 return token_buffer;
8526 }
8527
8529 // diagnostics
8531
8533 constexpr position_t get_position() const noexcept
8534 {
8535 return position;
8536 }
8537
8541 std::string get_token_string() const
8542 {
8543 // escape control characters
8544 std::string result;
8545 for (const auto c : token_string)
8546 {
8547 if (static_cast<unsigned char>(c) <= '\x1F')
8548 {
8549 // escape control characters
8550 std::array<char, 9> cs{{}};
8551 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8552 result += cs.data();
8553 }
8554 else
8555 {
8556 // add character as is
8557 result.push_back(static_cast<std::string::value_type>(c));
8558 }
8559 }
8560
8561 return result;
8562 }
8563
8565 JSON_HEDLEY_RETURNS_NON_NULL
8566 constexpr const char* get_error_message() const noexcept
8567 {
8568 return error_message;
8569 }
8570
8572 // actual scanner
8574
8580 {
8581 if (get() == 0xEF)
8582 {
8583 // check if we completely parse the BOM
8584 return get() == 0xBB && get() == 0xBF;
8585 }
8586
8587 // the first character is not the beginning of the BOM; unget it to
8588 // process is later
8589 unget();
8590 return true;
8591 }
8592
8593 void skip_whitespace()
8594 {
8595 do
8596 {
8597 get();
8598 }
8599 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8600 }
8601
8602 token_type scan()
8603 {
8604 // initially, skip the BOM
8605 if (position.chars_read_total == 0 && !skip_bom())
8606 {
8607 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8608 return token_type::parse_error;
8609 }
8610
8611 // read the next character and ignore whitespace
8612 skip_whitespace();
8613
8614 // ignore comments
8615 while (ignore_comments && current == '/')
8616 {
8617 if (!scan_comment())
8618 {
8619 return token_type::parse_error;
8620 }
8621
8622 // skip following whitespace
8623 skip_whitespace();
8624 }
8625
8626 switch (current)
8627 {
8628 // structural characters
8629 case '[':
8630 return token_type::begin_array;
8631 case ']':
8632 return token_type::end_array;
8633 case '{':
8634 return token_type::begin_object;
8635 case '}':
8636 return token_type::end_object;
8637 case ':':
8638 return token_type::name_separator;
8639 case ',':
8640 return token_type::value_separator;
8641
8642 // literals
8643 case 't':
8644 {
8645 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')}};
8646 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8647 }
8648 case 'f':
8649 {
8650 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')}};
8651 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8652 }
8653 case 'n':
8654 {
8655 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')}};
8656 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8657 }
8658
8659 // string
8660 case '\"':
8661 return scan_string();
8662
8663 // number
8664 case '-':
8665 case '0':
8666 case '1':
8667 case '2':
8668 case '3':
8669 case '4':
8670 case '5':
8671 case '6':
8672 case '7':
8673 case '8':
8674 case '9':
8675 return scan_number();
8676
8677 // end of input (the null byte is needed when parsing from
8678 // string literals)
8679 case '\0':
8680 case char_traits<char_type>::eof():
8681 return token_type::end_of_input;
8682
8683 // error
8684 default:
8685 error_message = "invalid literal";
8686 return token_type::parse_error;
8687 }
8688 }
8689
8690 private:
8692 InputAdapterType ia;
8693
8695 const bool ignore_comments = false;
8696
8698 char_int_type current = char_traits<char_type>::eof();
8699
8701 bool next_unget = false;
8702
8704 position_t position {};
8705
8707 std::vector<char_type> token_string {};
8708
8710 string_t token_buffer {};
8711
8713 const char* error_message = "";
8714
8715 // number values
8716 number_integer_t value_integer = 0;
8717 number_unsigned_t value_unsigned = 0;
8718 number_float_t value_float = 0;
8719
8721 const char_int_type decimal_point_char = '.';
8723 std::size_t decimal_point_position = std::string::npos;
8724};
8725
8726} // namespace detail
8727NLOHMANN_JSON_NAMESPACE_END
8728
8729// #include <nlohmann/detail/macro_scope.hpp>
8730
8731// #include <nlohmann/detail/string_concat.hpp>
8732
8733NLOHMANN_JSON_NAMESPACE_BEGIN
8734
8743template<typename BasicJsonType>
8744struct json_sax
8745{
8746 using number_integer_t = typename BasicJsonType::number_integer_t;
8747 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8748 using number_float_t = typename BasicJsonType::number_float_t;
8749 using string_t = typename BasicJsonType::string_t;
8750 using binary_t = typename BasicJsonType::binary_t;
8751
8756 virtual bool null() = 0;
8757
8763 virtual bool boolean(bool val) = 0;
8764
8770 virtual bool number_integer(number_integer_t val) = 0;
8771
8777 virtual bool number_unsigned(number_unsigned_t val) = 0;
8778
8785 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8786
8793 virtual bool string(string_t& val) = 0;
8794
8801 virtual bool binary(binary_t& val) = 0;
8802
8809 virtual bool start_object(std::size_t elements) = 0;
8810
8817 virtual bool key(string_t& val) = 0;
8818
8823 virtual bool end_object() = 0;
8824
8831 virtual bool start_array(std::size_t elements) = 0;
8832
8837 virtual bool end_array() = 0;
8838
8846 virtual bool parse_error(std::size_t position,
8847 const std::string& last_token,
8848 const detail::exception& ex) = 0;
8849
8850 json_sax() = default;
8851 json_sax(const json_sax&) = default;
8852 json_sax(json_sax&&) noexcept = default;
8853 json_sax& operator=(const json_sax&) = default;
8854 json_sax& operator=(json_sax&&) noexcept = default;
8855 virtual ~json_sax() = default;
8856};
8857
8858namespace detail
8859{
8860constexpr std::size_t unknown_size()
8861{
8862 return (std::numeric_limits<std::size_t>::max)();
8863}
8864
8878template<typename BasicJsonType, typename InputAdapterType>
8880{
8881 public:
8882 using number_integer_t = typename BasicJsonType::number_integer_t;
8883 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8884 using number_float_t = typename BasicJsonType::number_float_t;
8885 using string_t = typename BasicJsonType::string_t;
8886 using binary_t = typename BasicJsonType::binary_t;
8888
8894 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8895 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8896 {}
8897
8898 // make class move-only
8900 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8901 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
8902 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8903 ~json_sax_dom_parser() = default;
8904
8905 bool null()
8906 {
8907 handle_value(nullptr);
8908 return true;
8909 }
8910
8911 bool boolean(bool val)
8912 {
8913 handle_value(val);
8914 return true;
8915 }
8916
8917 bool number_integer(number_integer_t val)
8918 {
8919 handle_value(val);
8920 return true;
8921 }
8922
8923 bool number_unsigned(number_unsigned_t val)
8924 {
8925 handle_value(val);
8926 return true;
8927 }
8928
8929 bool number_float(number_float_t val, const string_t& /*unused*/)
8930 {
8931 handle_value(val);
8932 return true;
8933 }
8934
8935 bool string(string_t& val)
8936 {
8937 handle_value(val);
8938 return true;
8939 }
8940
8941 bool binary(binary_t& val)
8942 {
8943 handle_value(std::move(val));
8944 return true;
8945 }
8946
8947 bool start_object(std::size_t len)
8948 {
8949 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8950
8951#if JSON_DIAGNOSTIC_POSITIONS
8952 // Manually set the start position of the object here.
8953 // Ensure this is after the call to handle_value to ensure correct start position.
8954 if (m_lexer_ref)
8955 {
8956 // Lexer has read the first character of the object, so
8957 // subtract 1 from the position to get the correct start position.
8958 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8959 }
8960#endif
8961
8962 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8963 {
8964 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8965 }
8966
8967 return true;
8968 }
8969
8970 bool key(string_t& val)
8971 {
8972 JSON_ASSERT(!ref_stack.empty());
8973 JSON_ASSERT(ref_stack.back()->is_object());
8974
8975 // add null at the given key and store the reference for later
8976 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8977 return true;
8978 }
8979
8980 bool end_object()
8981 {
8982 JSON_ASSERT(!ref_stack.empty());
8983 JSON_ASSERT(ref_stack.back()->is_object());
8984
8985#if JSON_DIAGNOSTIC_POSITIONS
8986 if (m_lexer_ref)
8987 {
8988 // Lexer's position is past the closing brace, so set that as the end position.
8989 ref_stack.back()->end_position = m_lexer_ref->get_position();
8990 }
8991#endif
8992
8993 ref_stack.back()->set_parents();
8994 ref_stack.pop_back();
8995 return true;
8996 }
8997
8998 bool start_array(std::size_t len)
8999 {
9000 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
9001
9002#if JSON_DIAGNOSTIC_POSITIONS
9003 // Manually set the start position of the array here.
9004 // Ensure this is after the call to handle_value to ensure correct start position.
9005 if (m_lexer_ref)
9006 {
9007 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9008 }
9009#endif
9010
9011 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9012 {
9013 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9014 }
9015
9016 return true;
9017 }
9018
9019 bool end_array()
9020 {
9021 JSON_ASSERT(!ref_stack.empty());
9022 JSON_ASSERT(ref_stack.back()->is_array());
9023
9024#if JSON_DIAGNOSTIC_POSITIONS
9025 if (m_lexer_ref)
9026 {
9027 // Lexer's position is past the closing bracket, so set that as the end position.
9028 ref_stack.back()->end_position = m_lexer_ref->get_position();
9029 }
9030#endif
9031
9032 ref_stack.back()->set_parents();
9033 ref_stack.pop_back();
9034 return true;
9035 }
9036
9037 template<class Exception>
9038 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9039 const Exception& ex)
9040 {
9041 errored = true;
9042 static_cast<void>(ex);
9043 if (allow_exceptions)
9044 {
9045 JSON_THROW(ex);
9046 }
9047 return false;
9048 }
9049
9050 constexpr bool is_errored() const
9051 {
9052 return errored;
9053 }
9054
9055 private:
9056
9057#if JSON_DIAGNOSTIC_POSITIONS
9058 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9059 {
9060 if (m_lexer_ref)
9061 {
9062 // Lexer has read past the current field value, so set the end position to the current position.
9063 // The start position will be set below based on the length of the string representation
9064 // of the value.
9065 v.end_position = m_lexer_ref->get_position();
9066
9067 switch (v.type())
9068 {
9069 case value_t::boolean:
9070 {
9071 // 4 and 5 are the string length of "true" and "false"
9072 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9073 break;
9074 }
9075
9076 case value_t::null:
9077 {
9078 // 4 is the string length of "null"
9079 v.start_position = v.end_position - 4;
9080 break;
9081 }
9082
9083 case value_t::string:
9084 {
9085 // include the length of the quotes, which is 2
9086 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9087 break;
9088 }
9089
9090 // As we handle the start and end positions for values created during parsing,
9091 // we do not expect the following value type to be called. Regardless, set the positions
9092 // in case this is created manually or through a different constructor. Exclude from lcov
9093 // since the exact condition of this switch is esoteric.
9094 // LCOV_EXCL_START
9095 case value_t::discarded:
9096 {
9097 v.end_position = std::string::npos;
9098 v.start_position = v.end_position;
9099 break;
9100 }
9101 // LCOV_EXCL_STOP
9102 case value_t::binary:
9103 case value_t::number_integer:
9104 case value_t::number_unsigned:
9105 case value_t::number_float:
9106 {
9107 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9108 break;
9109 }
9110 case value_t::object:
9111 case value_t::array:
9112 {
9113 // object and array are handled in start_object() and start_array() handlers
9114 // skip setting the values here.
9115 break;
9116 }
9117 default: // LCOV_EXCL_LINE
9118 // Handle all possible types discretely, default handler should never be reached.
9119 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9120 }
9121 }
9122 }
9123#endif
9124
9131 template<typename Value>
9132 JSON_HEDLEY_RETURNS_NON_NULL
9133 BasicJsonType* handle_value(Value&& v)
9134 {
9135 if (ref_stack.empty())
9136 {
9137 root = BasicJsonType(std::forward<Value>(v));
9138
9139#if JSON_DIAGNOSTIC_POSITIONS
9140 handle_diagnostic_positions_for_json_value(root);
9141#endif
9142
9143 return &root;
9144 }
9145
9146 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9147
9148 if (ref_stack.back()->is_array())
9149 {
9150 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9151
9152#if JSON_DIAGNOSTIC_POSITIONS
9153 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9154#endif
9155
9156 return &(ref_stack.back()->m_data.m_value.array->back());
9157 }
9158
9159 JSON_ASSERT(ref_stack.back()->is_object());
9160 JSON_ASSERT(object_element);
9161 *object_element = BasicJsonType(std::forward<Value>(v));
9162
9163#if JSON_DIAGNOSTIC_POSITIONS
9164 handle_diagnostic_positions_for_json_value(*object_element);
9165#endif
9166
9167 return object_element;
9168 }
9169
9171 BasicJsonType& root;
9173 std::vector<BasicJsonType*> ref_stack {};
9175 BasicJsonType* object_element = nullptr;
9177 bool errored = false;
9179 const bool allow_exceptions = true;
9181 lexer_t* m_lexer_ref = nullptr;
9182};
9183
9184template<typename BasicJsonType, typename InputAdapterType>
9185class json_sax_dom_callback_parser
9186{
9187 public:
9188 using number_integer_t = typename BasicJsonType::number_integer_t;
9189 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9190 using number_float_t = typename BasicJsonType::number_float_t;
9191 using string_t = typename BasicJsonType::string_t;
9192 using binary_t = typename BasicJsonType::binary_t;
9193 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9194 using parse_event_t = typename BasicJsonType::parse_event_t;
9196
9197 json_sax_dom_callback_parser(BasicJsonType& r,
9198 parser_callback_t cb,
9199 const bool allow_exceptions_ = true,
9200 lexer_t* lexer_ = nullptr)
9201 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9202 {
9203 keep_stack.push_back(true);
9204 }
9205
9206 // make class move-only
9207 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
9208 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9209 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
9210 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9211 ~json_sax_dom_callback_parser() = default;
9212
9213 bool null()
9214 {
9215 handle_value(nullptr);
9216 return true;
9217 }
9218
9219 bool boolean(bool val)
9220 {
9221 handle_value(val);
9222 return true;
9223 }
9224
9225 bool number_integer(number_integer_t val)
9226 {
9227 handle_value(val);
9228 return true;
9229 }
9230
9231 bool number_unsigned(number_unsigned_t val)
9232 {
9233 handle_value(val);
9234 return true;
9235 }
9236
9237 bool number_float(number_float_t val, const string_t& /*unused*/)
9238 {
9239 handle_value(val);
9240 return true;
9241 }
9242
9243 bool string(string_t& val)
9244 {
9245 handle_value(val);
9246 return true;
9247 }
9248
9249 bool binary(binary_t& val)
9250 {
9251 handle_value(std::move(val));
9252 return true;
9253 }
9254
9255 bool start_object(std::size_t len)
9256 {
9257 // check callback for object start
9258 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9259 keep_stack.push_back(keep);
9260
9261 auto val = handle_value(BasicJsonType::value_t::object, true);
9262 ref_stack.push_back(val.second);
9263
9264 if (ref_stack.back())
9265 {
9266
9267#if JSON_DIAGNOSTIC_POSITIONS
9268 // Manually set the start position of the object here.
9269 // Ensure this is after the call to handle_value to ensure correct start position.
9270 if (m_lexer_ref)
9271 {
9272 // Lexer has read the first character of the object, so
9273 // subtract 1 from the position to get the correct start position.
9274 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9275 }
9276#endif
9277
9278 // check object limit
9279 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9280 {
9281 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9282 }
9283 }
9284 return true;
9285 }
9286
9287 bool key(string_t& val)
9288 {
9289 BasicJsonType k = BasicJsonType(val);
9290
9291 // check callback for the key
9292 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9293 key_keep_stack.push_back(keep);
9294
9295 // add discarded value at the given key and store the reference for later
9296 if (keep && ref_stack.back())
9297 {
9298 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9299 }
9300
9301 return true;
9302 }
9303
9304 bool end_object()
9305 {
9306 if (ref_stack.back())
9307 {
9308 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9309 {
9310 // discard object
9311 *ref_stack.back() = discarded;
9312
9313#if JSON_DIAGNOSTIC_POSITIONS
9314 // Set start/end positions for discarded object.
9315 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9316#endif
9317 }
9318 else
9319 {
9320
9321#if JSON_DIAGNOSTIC_POSITIONS
9322 if (m_lexer_ref)
9323 {
9324 // Lexer's position is past the closing brace, so set that as the end position.
9325 ref_stack.back()->end_position = m_lexer_ref->get_position();
9326 }
9327#endif
9328
9329 ref_stack.back()->set_parents();
9330 }
9331 }
9332
9333 JSON_ASSERT(!ref_stack.empty());
9334 JSON_ASSERT(!keep_stack.empty());
9335 ref_stack.pop_back();
9336 keep_stack.pop_back();
9337
9338 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9339 {
9340 // remove discarded value
9341 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9342 {
9343 if (it->is_discarded())
9344 {
9345 ref_stack.back()->erase(it);
9346 break;
9347 }
9348 }
9349 }
9350
9351 return true;
9352 }
9353
9354 bool start_array(std::size_t len)
9355 {
9356 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9357 keep_stack.push_back(keep);
9358
9359 auto val = handle_value(BasicJsonType::value_t::array, true);
9360 ref_stack.push_back(val.second);
9361
9362 if (ref_stack.back())
9363 {
9364
9365#if JSON_DIAGNOSTIC_POSITIONS
9366 // Manually set the start position of the array here.
9367 // Ensure this is after the call to handle_value to ensure correct start position.
9368 if (m_lexer_ref)
9369 {
9370 // Lexer has read the first character of the array, so
9371 // subtract 1 from the position to get the correct start position.
9372 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9373 }
9374#endif
9375
9376 // check array limit
9377 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9378 {
9379 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9380 }
9381 }
9382
9383 return true;
9384 }
9385
9386 bool end_array()
9387 {
9388 bool keep = true;
9389
9390 if (ref_stack.back())
9391 {
9392 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9393 if (keep)
9394 {
9395
9396#if JSON_DIAGNOSTIC_POSITIONS
9397 if (m_lexer_ref)
9398 {
9399 // Lexer's position is past the closing bracket, so set that as the end position.
9400 ref_stack.back()->end_position = m_lexer_ref->get_position();
9401 }
9402#endif
9403
9404 ref_stack.back()->set_parents();
9405 }
9406 else
9407 {
9408 // discard array
9409 *ref_stack.back() = discarded;
9410
9411#if JSON_DIAGNOSTIC_POSITIONS
9412 // Set start/end positions for discarded array.
9413 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9414#endif
9415 }
9416 }
9417
9418 JSON_ASSERT(!ref_stack.empty());
9419 JSON_ASSERT(!keep_stack.empty());
9420 ref_stack.pop_back();
9421 keep_stack.pop_back();
9422
9423 // remove discarded value
9424 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9425 {
9426 ref_stack.back()->m_data.m_value.array->pop_back();
9427 }
9428
9429 return true;
9430 }
9431
9432 template<class Exception>
9433 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9434 const Exception& ex)
9435 {
9436 errored = true;
9437 static_cast<void>(ex);
9438 if (allow_exceptions)
9439 {
9440 JSON_THROW(ex);
9441 }
9442 return false;
9443 }
9444
9445 constexpr bool is_errored() const
9446 {
9447 return errored;
9448 }
9449
9450 private:
9451
9452#if JSON_DIAGNOSTIC_POSITIONS
9453 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9454 {
9455 if (m_lexer_ref)
9456 {
9457 // Lexer has read past the current field value, so set the end position to the current position.
9458 // The start position will be set below based on the length of the string representation
9459 // of the value.
9460 v.end_position = m_lexer_ref->get_position();
9461
9462 switch (v.type())
9463 {
9464 case value_t::boolean:
9465 {
9466 // 4 and 5 are the string length of "true" and "false"
9467 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9468 break;
9469 }
9470
9471 case value_t::null:
9472 {
9473 // 4 is the string length of "null"
9474 v.start_position = v.end_position - 4;
9475 break;
9476 }
9477
9478 case value_t::string:
9479 {
9480 // include the length of the quotes, which is 2
9481 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9482 break;
9483 }
9484
9485 case value_t::discarded:
9486 {
9487 v.end_position = std::string::npos;
9488 v.start_position = v.end_position;
9489 break;
9490 }
9491
9492 case value_t::binary:
9496 {
9497 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9498 break;
9499 }
9500
9501 case value_t::object:
9502 case value_t::array:
9503 {
9504 // object and array are handled in start_object() and start_array() handlers
9505 // skip setting the values here.
9506 break;
9507 }
9508 default: // LCOV_EXCL_LINE
9509 // Handle all possible types discretely, default handler should never be reached.
9510 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9511 }
9512 }
9513 }
9514#endif
9515
9531 template<typename Value>
9532 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9533 {
9534 JSON_ASSERT(!keep_stack.empty());
9535
9536 // do not handle this value if we know it would be added to a discarded
9537 // container
9538 if (!keep_stack.back())
9539 {
9540 return {false, nullptr};
9541 }
9542
9543 // create value
9544 auto value = BasicJsonType(std::forward<Value>(v));
9545
9546#if JSON_DIAGNOSTIC_POSITIONS
9547 handle_diagnostic_positions_for_json_value(value);
9548#endif
9549
9550 // check callback
9551 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9552
9553 // do not handle this value if we just learnt it shall be discarded
9554 if (!keep)
9555 {
9556 return {false, nullptr};
9557 }
9558
9559 if (ref_stack.empty())
9560 {
9561 root = std::move(value);
9562 return {true, & root};
9563 }
9564
9565 // skip this value if we already decided to skip the parent
9566 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9567 if (!ref_stack.back())
9568 {
9569 return {false, nullptr};
9570 }
9571
9572 // we now only expect arrays and objects
9573 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9574
9575 // array
9576 if (ref_stack.back()->is_array())
9577 {
9578 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9579 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9580 }
9581
9582 // object
9583 JSON_ASSERT(ref_stack.back()->is_object());
9584 // check if we should store an element for the current key
9585 JSON_ASSERT(!key_keep_stack.empty());
9586 const bool store_element = key_keep_stack.back();
9587 key_keep_stack.pop_back();
9588
9589 if (!store_element)
9590 {
9591 return {false, nullptr};
9592 }
9593
9594 JSON_ASSERT(object_element);
9595 *object_element = std::move(value);
9596 return {true, object_element};
9597 }
9598
9600 BasicJsonType& root;
9602 std::vector<BasicJsonType*> ref_stack {};
9604 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9606 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9608 BasicJsonType* object_element = nullptr;
9610 bool errored = false;
9612 const parser_callback_t callback = nullptr;
9614 const bool allow_exceptions = true;
9616 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9618 lexer_t* m_lexer_ref = nullptr;
9619};
9620
9621template<typename BasicJsonType>
9623{
9624 public:
9625 using number_integer_t = typename BasicJsonType::number_integer_t;
9626 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9627 using number_float_t = typename BasicJsonType::number_float_t;
9628 using string_t = typename BasicJsonType::string_t;
9629 using binary_t = typename BasicJsonType::binary_t;
9630
9631 bool null()
9632 {
9633 return true;
9634 }
9635
9636 bool boolean(bool /*unused*/)
9637 {
9638 return true;
9639 }
9640
9641 bool number_integer(number_integer_t /*unused*/)
9642 {
9643 return true;
9644 }
9645
9646 bool number_unsigned(number_unsigned_t /*unused*/)
9647 {
9648 return true;
9649 }
9650
9651 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9652 {
9653 return true;
9654 }
9655
9656 bool string(string_t& /*unused*/)
9657 {
9658 return true;
9659 }
9660
9661 bool binary(binary_t& /*unused*/)
9662 {
9663 return true;
9664 }
9665
9666 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9667 {
9668 return true;
9669 }
9670
9671 bool key(string_t& /*unused*/)
9672 {
9673 return true;
9674 }
9675
9676 bool end_object()
9677 {
9678 return true;
9679 }
9680
9681 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9682 {
9683 return true;
9684 }
9685
9686 bool end_array()
9687 {
9688 return true;
9689 }
9690
9691 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9692 {
9693 return false;
9694 }
9695};
9696
9697} // namespace detail
9698NLOHMANN_JSON_NAMESPACE_END
9699
9700// #include <nlohmann/detail/input/lexer.hpp>
9701
9702// #include <nlohmann/detail/macro_scope.hpp>
9703
9704// #include <nlohmann/detail/meta/is_sax.hpp>
9705// __ _____ _____ _____
9706// __| | __| | | | JSON for Modern C++
9707// | | |__ | | | | | | version 3.12.0
9708// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9709//
9710// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
9711// SPDX-License-Identifier: MIT
9712
9713
9714
9715#include <cstdint> // size_t
9716#include <utility> // declval
9717#include <string> // string
9718
9719// #include <nlohmann/detail/abi_macros.hpp>
9720
9721// #include <nlohmann/detail/meta/detected.hpp>
9722
9723// #include <nlohmann/detail/meta/type_traits.hpp>
9724
9725
9726NLOHMANN_JSON_NAMESPACE_BEGIN
9727namespace detail
9728{
9729
9730template<typename T>
9731using null_function_t = decltype(std::declval<T&>().null());
9732
9733template<typename T>
9734using boolean_function_t =
9735 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9736
9737template<typename T, typename Integer>
9738using number_integer_function_t =
9739 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9740
9741template<typename T, typename Unsigned>
9742using number_unsigned_function_t =
9743 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9744
9745template<typename T, typename Float, typename String>
9746using number_float_function_t = decltype(std::declval<T&>().number_float(
9747 std::declval<Float>(), std::declval<const String&>()));
9748
9749template<typename T, typename String>
9750using string_function_t =
9751 decltype(std::declval<T&>().string(std::declval<String&>()));
9752
9753template<typename T, typename Binary>
9754using binary_function_t =
9755 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9756
9757template<typename T>
9758using start_object_function_t =
9759 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9760
9761template<typename T, typename String>
9762using key_function_t =
9763 decltype(std::declval<T&>().key(std::declval<String&>()));
9764
9765template<typename T>
9766using end_object_function_t = decltype(std::declval<T&>().end_object());
9767
9768template<typename T>
9769using start_array_function_t =
9770 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9771
9772template<typename T>
9773using end_array_function_t = decltype(std::declval<T&>().end_array());
9774
9775template<typename T, typename Exception>
9776using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9777 std::declval<std::size_t>(), std::declval<const std::string&>(),
9778 std::declval<const Exception&>()));
9779
9780template<typename SAX, typename BasicJsonType>
9782{
9783 private:
9785 "BasicJsonType must be of type basic_json<...>");
9786
9787 using number_integer_t = typename BasicJsonType::number_integer_t;
9788 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9789 using number_float_t = typename BasicJsonType::number_float_t;
9790 using string_t = typename BasicJsonType::string_t;
9791 using binary_t = typename BasicJsonType::binary_t;
9792 using exception_t = typename BasicJsonType::exception;
9793
9794 public:
9795 static constexpr bool value =
9796 is_detected_exact<bool, null_function_t, SAX>::value &&
9797 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9798 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9799 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9800 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9801 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9802 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9803 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9804 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9805 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9806 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9807 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9808 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9809};
9810
9811template<typename SAX, typename BasicJsonType>
9813{
9814 private:
9816 "BasicJsonType must be of type basic_json<...>");
9817
9818 using number_integer_t = typename BasicJsonType::number_integer_t;
9819 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9820 using number_float_t = typename BasicJsonType::number_float_t;
9821 using string_t = typename BasicJsonType::string_t;
9822 using binary_t = typename BasicJsonType::binary_t;
9823 using exception_t = typename BasicJsonType::exception;
9824
9825 public:
9826 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9827 "Missing/invalid function: bool null()");
9828 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9829 "Missing/invalid function: bool boolean(bool)");
9830 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9831 "Missing/invalid function: bool boolean(bool)");
9832 static_assert(
9833 is_detected_exact<bool, number_integer_function_t, SAX,
9834 number_integer_t>::value,
9835 "Missing/invalid function: bool number_integer(number_integer_t)");
9836 static_assert(
9837 is_detected_exact<bool, number_unsigned_function_t, SAX,
9838 number_unsigned_t>::value,
9839 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9840 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9841 number_float_t, string_t>::value,
9842 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9843 static_assert(
9844 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9845 "Missing/invalid function: bool string(string_t&)");
9846 static_assert(
9847 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9848 "Missing/invalid function: bool binary(binary_t&)");
9849 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9850 "Missing/invalid function: bool start_object(std::size_t)");
9851 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9852 "Missing/invalid function: bool key(string_t&)");
9853 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9854 "Missing/invalid function: bool end_object()");
9855 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9856 "Missing/invalid function: bool start_array(std::size_t)");
9857 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9858 "Missing/invalid function: bool end_array()");
9859 static_assert(
9860 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9861 "Missing/invalid function: bool parse_error(std::size_t, const "
9862 "std::string&, const exception&)");
9863};
9864
9865} // namespace detail
9866NLOHMANN_JSON_NAMESPACE_END
9867
9868// #include <nlohmann/detail/meta/type_traits.hpp>
9869
9870// #include <nlohmann/detail/string_concat.hpp>
9871
9872// #include <nlohmann/detail/value_t.hpp>
9873
9874
9875NLOHMANN_JSON_NAMESPACE_BEGIN
9876namespace detail
9877{
9878
9886
9894inline bool little_endianness(int num = 1) noexcept
9895{
9896 return *reinterpret_cast<char*>(&num) == 1;
9897}
9898
9900// binary reader //
9902
9906template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9908{
9909 using number_integer_t = typename BasicJsonType::number_integer_t;
9910 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9911 using number_float_t = typename BasicJsonType::number_float_t;
9912 using string_t = typename BasicJsonType::string_t;
9913 using binary_t = typename BasicJsonType::binary_t;
9914 using json_sax_t = SAX;
9915 using char_type = typename InputAdapterType::char_type;
9916 using char_int_type = typename char_traits<char_type>::int_type;
9917
9918 public:
9924 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9925 {
9927 }
9928
9929 // make class move-only
9930 binary_reader(const binary_reader&) = delete;
9931 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9932 binary_reader& operator=(const binary_reader&) = delete;
9933 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9934 ~binary_reader() = default;
9935
9944 JSON_HEDLEY_NON_NULL(3)
9945 bool sax_parse(const input_format_t format,
9946 json_sax_t* sax_,
9947 const bool strict = true,
9948 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9949 {
9950 sax = sax_;
9951 bool result = false;
9952
9953 switch (format)
9954 {
9955 case input_format_t::bson:
9956 result = parse_bson_internal();
9957 break;
9958
9959 case input_format_t::cbor:
9960 result = parse_cbor_internal(true, tag_handler);
9961 break;
9962
9963 case input_format_t::msgpack:
9964 result = parse_msgpack_internal();
9965 break;
9966
9967 case input_format_t::ubjson:
9968 case input_format_t::bjdata:
9969 result = parse_ubjson_internal();
9970 break;
9971
9972 case input_format_t::json: // LCOV_EXCL_LINE
9973 default: // LCOV_EXCL_LINE
9974 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9975 }
9976
9977 // strict mode: next byte must be EOF
9978 if (result && strict)
9979 {
9980 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9981 {
9982 get_ignore_noop();
9983 }
9984 else
9985 {
9986 get();
9987 }
9988
9989 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9990 {
9991 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9992 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9993 }
9994 }
9995
9996 return result;
9997 }
9998
9999 private:
10001 // BSON //
10003
10008 bool parse_bson_internal()
10009 {
10010 std::int32_t document_size{};
10011 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10012
10013 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
10014 {
10015 return false;
10016 }
10017
10018 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
10019 {
10020 return false;
10021 }
10022
10023 return sax->end_object();
10024 }
10025
10033 bool get_bson_cstr(string_t& result)
10034 {
10035 auto out = std::back_inserter(result);
10036 while (true)
10037 {
10038 get();
10039 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10040 {
10041 return false;
10042 }
10043 if (current == 0x00)
10044 {
10045 return true;
10046 }
10047 *out++ = static_cast<typename string_t::value_type>(current);
10048 }
10049 }
10050
10062 template<typename NumberType>
10063 bool get_bson_string(const NumberType len, string_t& result)
10064 {
10065 if (JSON_HEDLEY_UNLIKELY(len < 1))
10066 {
10067 auto last_token = get_token_string();
10068 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10069 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10070 }
10071
10072 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10073 }
10074
10084 template<typename NumberType>
10085 bool get_bson_binary(const NumberType len, binary_t& result)
10086 {
10087 if (JSON_HEDLEY_UNLIKELY(len < 0))
10088 {
10089 auto last_token = get_token_string();
10090 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10091 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10092 }
10093
10094 // All BSON binary values have a subtype
10095 std::uint8_t subtype{};
10096 get_number<std::uint8_t>(input_format_t::bson, subtype);
10097 result.set_subtype(subtype);
10098
10099 return get_binary(input_format_t::bson, len, result);
10100 }
10101
10112 bool parse_bson_element_internal(const char_int_type element_type,
10113 const std::size_t element_type_parse_position)
10114 {
10115 switch (element_type)
10116 {
10117 case 0x01: // double
10118 {
10119 double number{};
10120 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10121 }
10122
10123 case 0x02: // string
10124 {
10125 std::int32_t len{};
10126 string_t value;
10127 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10128 }
10129
10130 case 0x03: // object
10131 {
10132 return parse_bson_internal();
10133 }
10134
10135 case 0x04: // array
10136 {
10137 return parse_bson_array();
10138 }
10139
10140 case 0x05: // binary
10141 {
10142 std::int32_t len{};
10143 binary_t value;
10144 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10145 }
10146
10147 case 0x08: // boolean
10148 {
10149 return sax->boolean(get() != 0);
10150 }
10151
10152 case 0x0A: // null
10153 {
10154 return sax->null();
10155 }
10156
10157 case 0x10: // int32
10158 {
10159 std::int32_t value{};
10160 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10161 }
10162
10163 case 0x12: // int64
10164 {
10165 std::int64_t value{};
10166 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10167 }
10168
10169 case 0x11: // uint64
10170 {
10171 std::uint64_t value{};
10172 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10173 }
10174
10175 default: // anything else is not supported (yet)
10176 {
10177 std::array<char, 3> cr{{}};
10178 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10179 const std::string cr_str{cr.data()};
10180 return sax->parse_error(element_type_parse_position, cr_str,
10181 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10182 }
10183 }
10184 }
10185
10198 bool parse_bson_element_list(const bool is_array)
10199 {
10200 string_t key;
10201
10202 while (auto element_type = get())
10203 {
10204 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10205 {
10206 return false;
10207 }
10208
10209 const std::size_t element_type_parse_position = chars_read;
10210 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10211 {
10212 return false;
10213 }
10214
10215 if (!is_array && !sax->key(key))
10216 {
10217 return false;
10218 }
10219
10220 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10221 {
10222 return false;
10223 }
10224
10225 // get_bson_cstr only appends
10226 key.clear();
10227 }
10228
10229 return true;
10230 }
10231
10236 bool parse_bson_array()
10237 {
10238 std::int32_t document_size{};
10239 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10240
10241 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10242 {
10243 return false;
10244 }
10245
10246 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10247 {
10248 return false;
10249 }
10250
10251 return sax->end_array();
10252 }
10253
10255 // CBOR //
10257
10266 bool parse_cbor_internal(const bool get_char,
10267 const cbor_tag_handler_t tag_handler)
10268 {
10269 switch (get_char ? get() : current)
10270 {
10271 // EOF
10272 case char_traits<char_type>::eof():
10273 return unexpect_eof(input_format_t::cbor, "value");
10274
10275 // Integer 0x00..0x17 (0..23)
10276 case 0x00:
10277 case 0x01:
10278 case 0x02:
10279 case 0x03:
10280 case 0x04:
10281 case 0x05:
10282 case 0x06:
10283 case 0x07:
10284 case 0x08:
10285 case 0x09:
10286 case 0x0A:
10287 case 0x0B:
10288 case 0x0C:
10289 case 0x0D:
10290 case 0x0E:
10291 case 0x0F:
10292 case 0x10:
10293 case 0x11:
10294 case 0x12:
10295 case 0x13:
10296 case 0x14:
10297 case 0x15:
10298 case 0x16:
10299 case 0x17:
10300 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10301
10302 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10303 {
10304 std::uint8_t number{};
10305 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10306 }
10307
10308 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10309 {
10310 std::uint16_t number{};
10311 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10312 }
10313
10314 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10315 {
10316 std::uint32_t number{};
10317 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10318 }
10319
10320 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10321 {
10322 std::uint64_t number{};
10323 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10324 }
10325
10326 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10327 case 0x20:
10328 case 0x21:
10329 case 0x22:
10330 case 0x23:
10331 case 0x24:
10332 case 0x25:
10333 case 0x26:
10334 case 0x27:
10335 case 0x28:
10336 case 0x29:
10337 case 0x2A:
10338 case 0x2B:
10339 case 0x2C:
10340 case 0x2D:
10341 case 0x2E:
10342 case 0x2F:
10343 case 0x30:
10344 case 0x31:
10345 case 0x32:
10346 case 0x33:
10347 case 0x34:
10348 case 0x35:
10349 case 0x36:
10350 case 0x37:
10351 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10352
10353 case 0x38: // Negative integer (one-byte uint8_t follows)
10354 {
10355 std::uint8_t number{};
10356 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10357 }
10358
10359 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10360 {
10361 std::uint16_t number{};
10362 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10363 }
10364
10365 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10366 {
10367 std::uint32_t number{};
10368 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10369 }
10370
10371 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10372 {
10373 std::uint64_t number{};
10374 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10375 - static_cast<number_integer_t>(number));
10376 }
10377
10378 // Binary data (0x00..0x17 bytes follow)
10379 case 0x40:
10380 case 0x41:
10381 case 0x42:
10382 case 0x43:
10383 case 0x44:
10384 case 0x45:
10385 case 0x46:
10386 case 0x47:
10387 case 0x48:
10388 case 0x49:
10389 case 0x4A:
10390 case 0x4B:
10391 case 0x4C:
10392 case 0x4D:
10393 case 0x4E:
10394 case 0x4F:
10395 case 0x50:
10396 case 0x51:
10397 case 0x52:
10398 case 0x53:
10399 case 0x54:
10400 case 0x55:
10401 case 0x56:
10402 case 0x57:
10403 case 0x58: // Binary data (one-byte uint8_t for n follows)
10404 case 0x59: // Binary data (two-byte uint16_t for n follow)
10405 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10406 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10407 case 0x5F: // Binary data (indefinite length)
10408 {
10409 binary_t b;
10410 return get_cbor_binary(b) && sax->binary(b);
10411 }
10412
10413 // UTF-8 string (0x00..0x17 bytes follow)
10414 case 0x60:
10415 case 0x61:
10416 case 0x62:
10417 case 0x63:
10418 case 0x64:
10419 case 0x65:
10420 case 0x66:
10421 case 0x67:
10422 case 0x68:
10423 case 0x69:
10424 case 0x6A:
10425 case 0x6B:
10426 case 0x6C:
10427 case 0x6D:
10428 case 0x6E:
10429 case 0x6F:
10430 case 0x70:
10431 case 0x71:
10432 case 0x72:
10433 case 0x73:
10434 case 0x74:
10435 case 0x75:
10436 case 0x76:
10437 case 0x77:
10438 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10439 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10440 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10441 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10442 case 0x7F: // UTF-8 string (indefinite length)
10443 {
10444 string_t s;
10445 return get_cbor_string(s) && sax->string(s);
10446 }
10447
10448 // array (0x00..0x17 data items follow)
10449 case 0x80:
10450 case 0x81:
10451 case 0x82:
10452 case 0x83:
10453 case 0x84:
10454 case 0x85:
10455 case 0x86:
10456 case 0x87:
10457 case 0x88:
10458 case 0x89:
10459 case 0x8A:
10460 case 0x8B:
10461 case 0x8C:
10462 case 0x8D:
10463 case 0x8E:
10464 case 0x8F:
10465 case 0x90:
10466 case 0x91:
10467 case 0x92:
10468 case 0x93:
10469 case 0x94:
10470 case 0x95:
10471 case 0x96:
10472 case 0x97:
10473 return get_cbor_array(
10474 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10475
10476 case 0x98: // array (one-byte uint8_t for n follows)
10477 {
10478 std::uint8_t len{};
10479 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10480 }
10481
10482 case 0x99: // array (two-byte uint16_t for n follow)
10483 {
10484 std::uint16_t len{};
10485 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10486 }
10487
10488 case 0x9A: // array (four-byte uint32_t for n follow)
10489 {
10490 std::uint32_t len{};
10491 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10492 }
10493
10494 case 0x9B: // array (eight-byte uint64_t for n follow)
10495 {
10496 std::uint64_t len{};
10497 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10498 }
10499
10500 case 0x9F: // array (indefinite length)
10501 return get_cbor_array(detail::unknown_size(), tag_handler);
10502
10503 // map (0x00..0x17 pairs of data items follow)
10504 case 0xA0:
10505 case 0xA1:
10506 case 0xA2:
10507 case 0xA3:
10508 case 0xA4:
10509 case 0xA5:
10510 case 0xA6:
10511 case 0xA7:
10512 case 0xA8:
10513 case 0xA9:
10514 case 0xAA:
10515 case 0xAB:
10516 case 0xAC:
10517 case 0xAD:
10518 case 0xAE:
10519 case 0xAF:
10520 case 0xB0:
10521 case 0xB1:
10522 case 0xB2:
10523 case 0xB3:
10524 case 0xB4:
10525 case 0xB5:
10526 case 0xB6:
10527 case 0xB7:
10528 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10529
10530 case 0xB8: // map (one-byte uint8_t for n follows)
10531 {
10532 std::uint8_t len{};
10533 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10534 }
10535
10536 case 0xB9: // map (two-byte uint16_t for n follow)
10537 {
10538 std::uint16_t len{};
10539 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10540 }
10541
10542 case 0xBA: // map (four-byte uint32_t for n follow)
10543 {
10544 std::uint32_t len{};
10545 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10546 }
10547
10548 case 0xBB: // map (eight-byte uint64_t for n follow)
10549 {
10550 std::uint64_t len{};
10551 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10552 }
10553
10554 case 0xBF: // map (indefinite length)
10555 return get_cbor_object(detail::unknown_size(), tag_handler);
10556
10557 case 0xC6: // tagged item
10558 case 0xC7:
10559 case 0xC8:
10560 case 0xC9:
10561 case 0xCA:
10562 case 0xCB:
10563 case 0xCC:
10564 case 0xCD:
10565 case 0xCE:
10566 case 0xCF:
10567 case 0xD0:
10568 case 0xD1:
10569 case 0xD2:
10570 case 0xD3:
10571 case 0xD4:
10572 case 0xD8: // tagged item (1 byte follows)
10573 case 0xD9: // tagged item (2 bytes follow)
10574 case 0xDA: // tagged item (4 bytes follow)
10575 case 0xDB: // tagged item (8 bytes follow)
10576 {
10577 switch (tag_handler)
10578 {
10579 case cbor_tag_handler_t::error:
10580 {
10581 auto last_token = get_token_string();
10582 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10583 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10584 }
10585
10586 case cbor_tag_handler_t::ignore:
10587 {
10588 // ignore binary subtype
10589 switch (current)
10590 {
10591 case 0xD8:
10592 {
10593 std::uint8_t subtype_to_ignore{};
10594 get_number(input_format_t::cbor, subtype_to_ignore);
10595 break;
10596 }
10597 case 0xD9:
10598 {
10599 std::uint16_t subtype_to_ignore{};
10600 get_number(input_format_t::cbor, subtype_to_ignore);
10601 break;
10602 }
10603 case 0xDA:
10604 {
10605 std::uint32_t subtype_to_ignore{};
10606 get_number(input_format_t::cbor, subtype_to_ignore);
10607 break;
10608 }
10609 case 0xDB:
10610 {
10611 std::uint64_t subtype_to_ignore{};
10612 get_number(input_format_t::cbor, subtype_to_ignore);
10613 break;
10614 }
10615 default:
10616 break;
10617 }
10618 return parse_cbor_internal(true, tag_handler);
10619 }
10620
10621 case cbor_tag_handler_t::store:
10622 {
10623 binary_t b;
10624 // use binary subtype and store in a binary container
10625 switch (current)
10626 {
10627 case 0xD8:
10628 {
10629 std::uint8_t subtype{};
10630 get_number(input_format_t::cbor, subtype);
10631 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10632 break;
10633 }
10634 case 0xD9:
10635 {
10636 std::uint16_t subtype{};
10637 get_number(input_format_t::cbor, subtype);
10638 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10639 break;
10640 }
10641 case 0xDA:
10642 {
10643 std::uint32_t subtype{};
10644 get_number(input_format_t::cbor, subtype);
10645 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10646 break;
10647 }
10648 case 0xDB:
10649 {
10650 std::uint64_t subtype{};
10651 get_number(input_format_t::cbor, subtype);
10652 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10653 break;
10654 }
10655 default:
10656 return parse_cbor_internal(true, tag_handler);
10657 }
10658 get();
10659 return get_cbor_binary(b) && sax->binary(b);
10660 }
10661
10662 default: // LCOV_EXCL_LINE
10663 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10664 return false; // LCOV_EXCL_LINE
10665 }
10666 }
10667
10668 case 0xF4: // false
10669 return sax->boolean(false);
10670
10671 case 0xF5: // true
10672 return sax->boolean(true);
10673
10674 case 0xF6: // null
10675 return sax->null();
10676
10677 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10678 {
10679 const auto byte1_raw = get();
10680 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10681 {
10682 return false;
10683 }
10684 const auto byte2_raw = get();
10685 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10686 {
10687 return false;
10688 }
10689
10690 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10691 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10692
10693 // Code from RFC 7049, Appendix D, Figure 3:
10694 // As half-precision floating-point numbers were only added
10695 // to IEEE 754 in 2008, today's programming platforms often
10696 // still only have limited support for them. It is very
10697 // easy to include at least decoding support for them even
10698 // without such support. An example of a small decoder for
10699 // half-precision floating-point numbers in the C language
10700 // is shown in Fig. 3.
10701 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10702 const double val = [&half]
10703 {
10704 const int exp = (half >> 10u) & 0x1Fu;
10705 const unsigned int mant = half & 0x3FFu;
10706 JSON_ASSERT(0 <= exp&& exp <= 32);
10707 JSON_ASSERT(mant <= 1024);
10708 switch (exp)
10709 {
10710 case 0:
10711 return std::ldexp(mant, -24);
10712 case 31:
10713 return (mant == 0)
10714 ? std::numeric_limits<double>::infinity()
10715 : std::numeric_limits<double>::quiet_NaN();
10716 default:
10717 return std::ldexp(mant + 1024, exp - 25);
10718 }
10719 }();
10720 return sax->number_float((half & 0x8000u) != 0
10721 ? static_cast<number_float_t>(-val)
10722 : static_cast<number_float_t>(val), "");
10723 }
10724
10725 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10726 {
10727 float number{};
10728 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10729 }
10730
10731 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10732 {
10733 double number{};
10734 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10735 }
10736
10737 default: // anything else (0xFF is handled inside the other types)
10738 {
10739 auto last_token = get_token_string();
10740 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10741 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10742 }
10743 }
10744 }
10745
10757 bool get_cbor_string(string_t& result)
10758 {
10759 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10760 {
10761 return false;
10762 }
10763
10764 switch (current)
10765 {
10766 // UTF-8 string (0x00..0x17 bytes follow)
10767 case 0x60:
10768 case 0x61:
10769 case 0x62:
10770 case 0x63:
10771 case 0x64:
10772 case 0x65:
10773 case 0x66:
10774 case 0x67:
10775 case 0x68:
10776 case 0x69:
10777 case 0x6A:
10778 case 0x6B:
10779 case 0x6C:
10780 case 0x6D:
10781 case 0x6E:
10782 case 0x6F:
10783 case 0x70:
10784 case 0x71:
10785 case 0x72:
10786 case 0x73:
10787 case 0x74:
10788 case 0x75:
10789 case 0x76:
10790 case 0x77:
10791 {
10792 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10793 }
10794
10795 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10796 {
10797 std::uint8_t len{};
10798 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10799 }
10800
10801 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10802 {
10803 std::uint16_t len{};
10804 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10805 }
10806
10807 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10808 {
10809 std::uint32_t len{};
10810 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10811 }
10812
10813 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10814 {
10815 std::uint64_t len{};
10816 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10817 }
10818
10819 case 0x7F: // UTF-8 string (indefinite length)
10820 {
10821 while (get() != 0xFF)
10822 {
10823 string_t chunk;
10824 if (!get_cbor_string(chunk))
10825 {
10826 return false;
10827 }
10828 result.append(chunk);
10829 }
10830 return true;
10831 }
10832
10833 default:
10834 {
10835 auto last_token = get_token_string();
10836 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10837 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10838 }
10839 }
10840 }
10841
10853 bool get_cbor_binary(binary_t& result)
10854 {
10855 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10856 {
10857 return false;
10858 }
10859
10860 switch (current)
10861 {
10862 // Binary data (0x00..0x17 bytes follow)
10863 case 0x40:
10864 case 0x41:
10865 case 0x42:
10866 case 0x43:
10867 case 0x44:
10868 case 0x45:
10869 case 0x46:
10870 case 0x47:
10871 case 0x48:
10872 case 0x49:
10873 case 0x4A:
10874 case 0x4B:
10875 case 0x4C:
10876 case 0x4D:
10877 case 0x4E:
10878 case 0x4F:
10879 case 0x50:
10880 case 0x51:
10881 case 0x52:
10882 case 0x53:
10883 case 0x54:
10884 case 0x55:
10885 case 0x56:
10886 case 0x57:
10887 {
10888 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10889 }
10890
10891 case 0x58: // Binary data (one-byte uint8_t for n follows)
10892 {
10893 std::uint8_t len{};
10894 return get_number(input_format_t::cbor, len) &&
10895 get_binary(input_format_t::cbor, len, result);
10896 }
10897
10898 case 0x59: // Binary data (two-byte uint16_t for n follow)
10899 {
10900 std::uint16_t len{};
10901 return get_number(input_format_t::cbor, len) &&
10902 get_binary(input_format_t::cbor, len, result);
10903 }
10904
10905 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10906 {
10907 std::uint32_t len{};
10908 return get_number(input_format_t::cbor, len) &&
10909 get_binary(input_format_t::cbor, len, result);
10910 }
10911
10912 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10913 {
10914 std::uint64_t len{};
10915 return get_number(input_format_t::cbor, len) &&
10916 get_binary(input_format_t::cbor, len, result);
10917 }
10918
10919 case 0x5F: // Binary data (indefinite length)
10920 {
10921 while (get() != 0xFF)
10922 {
10923 binary_t chunk;
10924 if (!get_cbor_binary(chunk))
10925 {
10926 return false;
10927 }
10928 result.insert(result.end(), chunk.begin(), chunk.end());
10929 }
10930 return true;
10931 }
10932
10933 default:
10934 {
10935 auto last_token = get_token_string();
10936 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10937 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));
10938 }
10939 }
10940 }
10941
10948 bool get_cbor_array(const std::size_t len,
10949 const cbor_tag_handler_t tag_handler)
10950 {
10951 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10952 {
10953 return false;
10954 }
10955
10956 if (len != detail::unknown_size())
10957 {
10958 for (std::size_t i = 0; i < len; ++i)
10959 {
10960 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10961 {
10962 return false;
10963 }
10964 }
10965 }
10966 else
10967 {
10968 while (get() != 0xFF)
10969 {
10970 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10971 {
10972 return false;
10973 }
10974 }
10975 }
10976
10977 return sax->end_array();
10978 }
10979
10986 bool get_cbor_object(const std::size_t len,
10987 const cbor_tag_handler_t tag_handler)
10988 {
10989 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10990 {
10991 return false;
10992 }
10993
10994 if (len != 0)
10995 {
10996 string_t key;
10997 if (len != detail::unknown_size())
10998 {
10999 for (std::size_t i = 0; i < len; ++i)
11000 {
11001 get();
11002 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11003 {
11004 return false;
11005 }
11006
11007 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11008 {
11009 return false;
11010 }
11011 key.clear();
11012 }
11013 }
11014 else
11015 {
11016 while (get() != 0xFF)
11017 {
11018 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
11019 {
11020 return false;
11021 }
11022
11023 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11024 {
11025 return false;
11026 }
11027 key.clear();
11028 }
11029 }
11030 }
11031
11032 return sax->end_object();
11033 }
11034
11036 // MsgPack //
11038
11042 bool parse_msgpack_internal()
11043 {
11044 switch (get())
11045 {
11046 // EOF
11047 case char_traits<char_type>::eof():
11048 return unexpect_eof(input_format_t::msgpack, "value");
11049
11050 // positive fixint
11051 case 0x00:
11052 case 0x01:
11053 case 0x02:
11054 case 0x03:
11055 case 0x04:
11056 case 0x05:
11057 case 0x06:
11058 case 0x07:
11059 case 0x08:
11060 case 0x09:
11061 case 0x0A:
11062 case 0x0B:
11063 case 0x0C:
11064 case 0x0D:
11065 case 0x0E:
11066 case 0x0F:
11067 case 0x10:
11068 case 0x11:
11069 case 0x12:
11070 case 0x13:
11071 case 0x14:
11072 case 0x15:
11073 case 0x16:
11074 case 0x17:
11075 case 0x18:
11076 case 0x19:
11077 case 0x1A:
11078 case 0x1B:
11079 case 0x1C:
11080 case 0x1D:
11081 case 0x1E:
11082 case 0x1F:
11083 case 0x20:
11084 case 0x21:
11085 case 0x22:
11086 case 0x23:
11087 case 0x24:
11088 case 0x25:
11089 case 0x26:
11090 case 0x27:
11091 case 0x28:
11092 case 0x29:
11093 case 0x2A:
11094 case 0x2B:
11095 case 0x2C:
11096 case 0x2D:
11097 case 0x2E:
11098 case 0x2F:
11099 case 0x30:
11100 case 0x31:
11101 case 0x32:
11102 case 0x33:
11103 case 0x34:
11104 case 0x35:
11105 case 0x36:
11106 case 0x37:
11107 case 0x38:
11108 case 0x39:
11109 case 0x3A:
11110 case 0x3B:
11111 case 0x3C:
11112 case 0x3D:
11113 case 0x3E:
11114 case 0x3F:
11115 case 0x40:
11116 case 0x41:
11117 case 0x42:
11118 case 0x43:
11119 case 0x44:
11120 case 0x45:
11121 case 0x46:
11122 case 0x47:
11123 case 0x48:
11124 case 0x49:
11125 case 0x4A:
11126 case 0x4B:
11127 case 0x4C:
11128 case 0x4D:
11129 case 0x4E:
11130 case 0x4F:
11131 case 0x50:
11132 case 0x51:
11133 case 0x52:
11134 case 0x53:
11135 case 0x54:
11136 case 0x55:
11137 case 0x56:
11138 case 0x57:
11139 case 0x58:
11140 case 0x59:
11141 case 0x5A:
11142 case 0x5B:
11143 case 0x5C:
11144 case 0x5D:
11145 case 0x5E:
11146 case 0x5F:
11147 case 0x60:
11148 case 0x61:
11149 case 0x62:
11150 case 0x63:
11151 case 0x64:
11152 case 0x65:
11153 case 0x66:
11154 case 0x67:
11155 case 0x68:
11156 case 0x69:
11157 case 0x6A:
11158 case 0x6B:
11159 case 0x6C:
11160 case 0x6D:
11161 case 0x6E:
11162 case 0x6F:
11163 case 0x70:
11164 case 0x71:
11165 case 0x72:
11166 case 0x73:
11167 case 0x74:
11168 case 0x75:
11169 case 0x76:
11170 case 0x77:
11171 case 0x78:
11172 case 0x79:
11173 case 0x7A:
11174 case 0x7B:
11175 case 0x7C:
11176 case 0x7D:
11177 case 0x7E:
11178 case 0x7F:
11179 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11180
11181 // fixmap
11182 case 0x80:
11183 case 0x81:
11184 case 0x82:
11185 case 0x83:
11186 case 0x84:
11187 case 0x85:
11188 case 0x86:
11189 case 0x87:
11190 case 0x88:
11191 case 0x89:
11192 case 0x8A:
11193 case 0x8B:
11194 case 0x8C:
11195 case 0x8D:
11196 case 0x8E:
11197 case 0x8F:
11198 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11199
11200 // fixarray
11201 case 0x90:
11202 case 0x91:
11203 case 0x92:
11204 case 0x93:
11205 case 0x94:
11206 case 0x95:
11207 case 0x96:
11208 case 0x97:
11209 case 0x98:
11210 case 0x99:
11211 case 0x9A:
11212 case 0x9B:
11213 case 0x9C:
11214 case 0x9D:
11215 case 0x9E:
11216 case 0x9F:
11217 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11218
11219 // fixstr
11220 case 0xA0:
11221 case 0xA1:
11222 case 0xA2:
11223 case 0xA3:
11224 case 0xA4:
11225 case 0xA5:
11226 case 0xA6:
11227 case 0xA7:
11228 case 0xA8:
11229 case 0xA9:
11230 case 0xAA:
11231 case 0xAB:
11232 case 0xAC:
11233 case 0xAD:
11234 case 0xAE:
11235 case 0xAF:
11236 case 0xB0:
11237 case 0xB1:
11238 case 0xB2:
11239 case 0xB3:
11240 case 0xB4:
11241 case 0xB5:
11242 case 0xB6:
11243 case 0xB7:
11244 case 0xB8:
11245 case 0xB9:
11246 case 0xBA:
11247 case 0xBB:
11248 case 0xBC:
11249 case 0xBD:
11250 case 0xBE:
11251 case 0xBF:
11252 case 0xD9: // str 8
11253 case 0xDA: // str 16
11254 case 0xDB: // str 32
11255 {
11256 string_t s;
11257 return get_msgpack_string(s) && sax->string(s);
11258 }
11259
11260 case 0xC0: // nil
11261 return sax->null();
11262
11263 case 0xC2: // false
11264 return sax->boolean(false);
11265
11266 case 0xC3: // true
11267 return sax->boolean(true);
11268
11269 case 0xC4: // bin 8
11270 case 0xC5: // bin 16
11271 case 0xC6: // bin 32
11272 case 0xC7: // ext 8
11273 case 0xC8: // ext 16
11274 case 0xC9: // ext 32
11275 case 0xD4: // fixext 1
11276 case 0xD5: // fixext 2
11277 case 0xD6: // fixext 4
11278 case 0xD7: // fixext 8
11279 case 0xD8: // fixext 16
11280 {
11281 binary_t b;
11282 return get_msgpack_binary(b) && sax->binary(b);
11283 }
11284
11285 case 0xCA: // float 32
11286 {
11287 float number{};
11288 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11289 }
11290
11291 case 0xCB: // float 64
11292 {
11293 double number{};
11294 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11295 }
11296
11297 case 0xCC: // uint 8
11298 {
11299 std::uint8_t number{};
11300 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11301 }
11302
11303 case 0xCD: // uint 16
11304 {
11305 std::uint16_t number{};
11306 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11307 }
11308
11309 case 0xCE: // uint 32
11310 {
11311 std::uint32_t number{};
11312 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11313 }
11314
11315 case 0xCF: // uint 64
11316 {
11317 std::uint64_t number{};
11318 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11319 }
11320
11321 case 0xD0: // int 8
11322 {
11323 std::int8_t number{};
11324 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11325 }
11326
11327 case 0xD1: // int 16
11328 {
11329 std::int16_t number{};
11330 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11331 }
11332
11333 case 0xD2: // int 32
11334 {
11335 std::int32_t number{};
11336 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11337 }
11338
11339 case 0xD3: // int 64
11340 {
11341 std::int64_t number{};
11342 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11343 }
11344
11345 case 0xDC: // array 16
11346 {
11347 std::uint16_t len{};
11348 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11349 }
11350
11351 case 0xDD: // array 32
11352 {
11353 std::uint32_t len{};
11354 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11355 }
11356
11357 case 0xDE: // map 16
11358 {
11359 std::uint16_t len{};
11360 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11361 }
11362
11363 case 0xDF: // map 32
11364 {
11365 std::uint32_t len{};
11366 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11367 }
11368
11369 // negative fixint
11370 case 0xE0:
11371 case 0xE1:
11372 case 0xE2:
11373 case 0xE3:
11374 case 0xE4:
11375 case 0xE5:
11376 case 0xE6:
11377 case 0xE7:
11378 case 0xE8:
11379 case 0xE9:
11380 case 0xEA:
11381 case 0xEB:
11382 case 0xEC:
11383 case 0xED:
11384 case 0xEE:
11385 case 0xEF:
11386 case 0xF0:
11387 case 0xF1:
11388 case 0xF2:
11389 case 0xF3:
11390 case 0xF4:
11391 case 0xF5:
11392 case 0xF6:
11393 case 0xF7:
11394 case 0xF8:
11395 case 0xF9:
11396 case 0xFA:
11397 case 0xFB:
11398 case 0xFC:
11399 case 0xFD:
11400 case 0xFE:
11401 case 0xFF:
11402 return sax->number_integer(static_cast<std::int8_t>(current));
11403
11404 default: // anything else
11405 {
11406 auto last_token = get_token_string();
11407 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11408 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11409 }
11410 }
11411 }
11412
11423 bool get_msgpack_string(string_t& result)
11424 {
11425 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11426 {
11427 return false;
11428 }
11429
11430 switch (current)
11431 {
11432 // fixstr
11433 case 0xA0:
11434 case 0xA1:
11435 case 0xA2:
11436 case 0xA3:
11437 case 0xA4:
11438 case 0xA5:
11439 case 0xA6:
11440 case 0xA7:
11441 case 0xA8:
11442 case 0xA9:
11443 case 0xAA:
11444 case 0xAB:
11445 case 0xAC:
11446 case 0xAD:
11447 case 0xAE:
11448 case 0xAF:
11449 case 0xB0:
11450 case 0xB1:
11451 case 0xB2:
11452 case 0xB3:
11453 case 0xB4:
11454 case 0xB5:
11455 case 0xB6:
11456 case 0xB7:
11457 case 0xB8:
11458 case 0xB9:
11459 case 0xBA:
11460 case 0xBB:
11461 case 0xBC:
11462 case 0xBD:
11463 case 0xBE:
11464 case 0xBF:
11465 {
11466 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11467 }
11468
11469 case 0xD9: // str 8
11470 {
11471 std::uint8_t len{};
11472 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11473 }
11474
11475 case 0xDA: // str 16
11476 {
11477 std::uint16_t len{};
11478 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11479 }
11480
11481 case 0xDB: // str 32
11482 {
11483 std::uint32_t len{};
11484 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11485 }
11486
11487 default:
11488 {
11489 auto last_token = get_token_string();
11490 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11491 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11492 }
11493 }
11494 }
11495
11506 bool get_msgpack_binary(binary_t& result)
11507 {
11508 // helper function to set the subtype
11509 auto assign_and_return_true = [&result](std::int8_t subtype)
11510 {
11511 result.set_subtype(static_cast<std::uint8_t>(subtype));
11512 return true;
11513 };
11514
11515 switch (current)
11516 {
11517 case 0xC4: // bin 8
11518 {
11519 std::uint8_t len{};
11520 return get_number(input_format_t::msgpack, len) &&
11521 get_binary(input_format_t::msgpack, len, result);
11522 }
11523
11524 case 0xC5: // bin 16
11525 {
11526 std::uint16_t len{};
11527 return get_number(input_format_t::msgpack, len) &&
11528 get_binary(input_format_t::msgpack, len, result);
11529 }
11530
11531 case 0xC6: // bin 32
11532 {
11533 std::uint32_t len{};
11534 return get_number(input_format_t::msgpack, len) &&
11535 get_binary(input_format_t::msgpack, len, result);
11536 }
11537
11538 case 0xC7: // ext 8
11539 {
11540 std::uint8_t len{};
11541 std::int8_t subtype{};
11542 return get_number(input_format_t::msgpack, len) &&
11543 get_number(input_format_t::msgpack, subtype) &&
11544 get_binary(input_format_t::msgpack, len, result) &&
11545 assign_and_return_true(subtype);
11546 }
11547
11548 case 0xC8: // ext 16
11549 {
11550 std::uint16_t len{};
11551 std::int8_t subtype{};
11552 return get_number(input_format_t::msgpack, len) &&
11553 get_number(input_format_t::msgpack, subtype) &&
11554 get_binary(input_format_t::msgpack, len, result) &&
11555 assign_and_return_true(subtype);
11556 }
11557
11558 case 0xC9: // ext 32
11559 {
11560 std::uint32_t len{};
11561 std::int8_t subtype{};
11562 return get_number(input_format_t::msgpack, len) &&
11563 get_number(input_format_t::msgpack, subtype) &&
11564 get_binary(input_format_t::msgpack, len, result) &&
11565 assign_and_return_true(subtype);
11566 }
11567
11568 case 0xD4: // fixext 1
11569 {
11570 std::int8_t subtype{};
11571 return get_number(input_format_t::msgpack, subtype) &&
11572 get_binary(input_format_t::msgpack, 1, result) &&
11573 assign_and_return_true(subtype);
11574 }
11575
11576 case 0xD5: // fixext 2
11577 {
11578 std::int8_t subtype{};
11579 return get_number(input_format_t::msgpack, subtype) &&
11580 get_binary(input_format_t::msgpack, 2, result) &&
11581 assign_and_return_true(subtype);
11582 }
11583
11584 case 0xD6: // fixext 4
11585 {
11586 std::int8_t subtype{};
11587 return get_number(input_format_t::msgpack, subtype) &&
11588 get_binary(input_format_t::msgpack, 4, result) &&
11589 assign_and_return_true(subtype);
11590 }
11591
11592 case 0xD7: // fixext 8
11593 {
11594 std::int8_t subtype{};
11595 return get_number(input_format_t::msgpack, subtype) &&
11596 get_binary(input_format_t::msgpack, 8, result) &&
11597 assign_and_return_true(subtype);
11598 }
11599
11600 case 0xD8: // fixext 16
11601 {
11602 std::int8_t subtype{};
11603 return get_number(input_format_t::msgpack, subtype) &&
11604 get_binary(input_format_t::msgpack, 16, result) &&
11605 assign_and_return_true(subtype);
11606 }
11607
11608 default: // LCOV_EXCL_LINE
11609 return false; // LCOV_EXCL_LINE
11610 }
11611 }
11612
11617 bool get_msgpack_array(const std::size_t len)
11618 {
11619 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11620 {
11621 return false;
11622 }
11623
11624 for (std::size_t i = 0; i < len; ++i)
11625 {
11626 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11627 {
11628 return false;
11629 }
11630 }
11631
11632 return sax->end_array();
11633 }
11634
11639 bool get_msgpack_object(const std::size_t len)
11640 {
11641 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11642 {
11643 return false;
11644 }
11645
11646 string_t key;
11647 for (std::size_t i = 0; i < len; ++i)
11648 {
11649 get();
11650 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11651 {
11652 return false;
11653 }
11654
11655 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11656 {
11657 return false;
11658 }
11659 key.clear();
11660 }
11661
11662 return sax->end_object();
11663 }
11664
11666 // UBJSON //
11668
11676 bool parse_ubjson_internal(const bool get_char = true)
11677 {
11678 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11679 }
11680
11695 bool get_ubjson_string(string_t& result, const bool get_char = true)
11696 {
11697 if (get_char)
11698 {
11699 get(); // TODO(niels): may we ignore N here?
11700 }
11701
11702 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11703 {
11704 return false;
11705 }
11706
11707 switch (current)
11708 {
11709 case 'U':
11710 {
11711 std::uint8_t len{};
11712 return get_number(input_format, len) && get_string(input_format, len, result);
11713 }
11714
11715 case 'i':
11716 {
11717 std::int8_t len{};
11718 return get_number(input_format, len) && get_string(input_format, len, result);
11719 }
11720
11721 case 'I':
11722 {
11723 std::int16_t len{};
11724 return get_number(input_format, len) && get_string(input_format, len, result);
11725 }
11726
11727 case 'l':
11728 {
11729 std::int32_t len{};
11730 return get_number(input_format, len) && get_string(input_format, len, result);
11731 }
11732
11733 case 'L':
11734 {
11735 std::int64_t len{};
11736 return get_number(input_format, len) && get_string(input_format, len, result);
11737 }
11738
11739 case 'u':
11740 {
11741 if (input_format != input_format_t::bjdata)
11742 {
11743 break;
11744 }
11745 std::uint16_t len{};
11746 return get_number(input_format, len) && get_string(input_format, len, result);
11747 }
11748
11749 case 'm':
11750 {
11751 if (input_format != input_format_t::bjdata)
11752 {
11753 break;
11754 }
11755 std::uint32_t len{};
11756 return get_number(input_format, len) && get_string(input_format, len, result);
11757 }
11758
11759 case 'M':
11760 {
11761 if (input_format != input_format_t::bjdata)
11762 {
11763 break;
11764 }
11765 std::uint64_t len{};
11766 return get_number(input_format, len) && get_string(input_format, len, result);
11767 }
11768
11769 default:
11770 break;
11771 }
11772 auto last_token = get_token_string();
11773 std::string message;
11774
11775 if (input_format != input_format_t::bjdata)
11776 {
11777 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11778 }
11779 else
11780 {
11781 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11782 }
11783 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11784 }
11785
11790 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11791 {
11792 std::pair<std::size_t, char_int_type> size_and_type;
11793 size_t dimlen = 0;
11794 bool no_ndarray = true;
11795
11796 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11797 {
11798 return false;
11799 }
11800
11801 if (size_and_type.first != npos)
11802 {
11803 if (size_and_type.second != 0)
11804 {
11805 if (size_and_type.second != 'N')
11806 {
11807 for (std::size_t i = 0; i < size_and_type.first; ++i)
11808 {
11809 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11810 {
11811 return false;
11812 }
11813 dim.push_back(dimlen);
11814 }
11815 }
11816 }
11817 else
11818 {
11819 for (std::size_t i = 0; i < size_and_type.first; ++i)
11820 {
11821 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11822 {
11823 return false;
11824 }
11825 dim.push_back(dimlen);
11826 }
11827 }
11828 }
11829 else
11830 {
11831 while (current != ']')
11832 {
11833 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11834 {
11835 return false;
11836 }
11837 dim.push_back(dimlen);
11838 get_ignore_noop();
11839 }
11840 }
11841 return true;
11842 }
11843
11855 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11856 {
11857 if (prefix == 0)
11858 {
11859 prefix = get_ignore_noop();
11860 }
11861
11862 switch (prefix)
11863 {
11864 case 'U':
11865 {
11866 std::uint8_t number{};
11867 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11868 {
11869 return false;
11870 }
11871 result = static_cast<std::size_t>(number);
11872 return true;
11873 }
11874
11875 case 'i':
11876 {
11877 std::int8_t number{};
11878 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11879 {
11880 return false;
11881 }
11882 if (number < 0)
11883 {
11884 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11885 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11886 }
11887 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11888 return true;
11889 }
11890
11891 case 'I':
11892 {
11893 std::int16_t number{};
11894 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11895 {
11896 return false;
11897 }
11898 if (number < 0)
11899 {
11900 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11901 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11902 }
11903 result = static_cast<std::size_t>(number);
11904 return true;
11905 }
11906
11907 case 'l':
11908 {
11909 std::int32_t number{};
11910 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11911 {
11912 return false;
11913 }
11914 if (number < 0)
11915 {
11916 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11917 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11918 }
11919 result = static_cast<std::size_t>(number);
11920 return true;
11921 }
11922
11923 case 'L':
11924 {
11925 std::int64_t number{};
11926 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11927 {
11928 return false;
11929 }
11930 if (number < 0)
11931 {
11932 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11933 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11934 }
11935 if (!value_in_range_of<std::size_t>(number))
11936 {
11937 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11938 exception_message(input_format, "integer value overflow", "size"), nullptr));
11939 }
11940 result = static_cast<std::size_t>(number);
11941 return true;
11942 }
11943
11944 case 'u':
11945 {
11946 if (input_format != input_format_t::bjdata)
11947 {
11948 break;
11949 }
11950 std::uint16_t number{};
11951 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11952 {
11953 return false;
11954 }
11955 result = static_cast<std::size_t>(number);
11956 return true;
11957 }
11958
11959 case 'm':
11960 {
11961 if (input_format != input_format_t::bjdata)
11962 {
11963 break;
11964 }
11965 std::uint32_t number{};
11966 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11967 {
11968 return false;
11969 }
11970 result = conditional_static_cast<std::size_t>(number);
11971 return true;
11972 }
11973
11974 case 'M':
11975 {
11976 if (input_format != input_format_t::bjdata)
11977 {
11978 break;
11979 }
11980 std::uint64_t number{};
11981 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11982 {
11983 return false;
11984 }
11985 if (!value_in_range_of<std::size_t>(number))
11986 {
11987 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11988 exception_message(input_format, "integer value overflow", "size"), nullptr));
11989 }
11990 result = detail::conditional_static_cast<std::size_t>(number);
11991 return true;
11992 }
11993
11994 case '[':
11995 {
11996 if (input_format != input_format_t::bjdata)
11997 {
11998 break;
11999 }
12000 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
12001 {
12002 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));
12003 }
12004 std::vector<size_t> dim;
12005 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
12006 {
12007 return false;
12008 }
12009 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
12010 {
12011 result = dim.at(dim.size() - 1);
12012 return true;
12013 }
12014 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
12015 {
12016 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
12017 {
12018 if ( i == 0 )
12019 {
12020 result = 0;
12021 return true;
12022 }
12023 }
12024
12025 string_t key = "_ArraySize_";
12026 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12027 {
12028 return false;
12029 }
12030 result = 1;
12031 for (auto i : dim)
12032 {
12033 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12034 // This check must happen before multiplication since overflow detection after the fact is unreliable
12035 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12036 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12037 {
12038 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));
12039 }
12040 result *= i;
12041 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12042 if (result == 0 || result == npos)
12043 {
12044 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));
12045 }
12046 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12047 {
12048 return false;
12049 }
12050 }
12051 is_ndarray = true;
12052 return sax->end_array();
12053 }
12054 result = 0;
12055 return true;
12056 }
12057
12058 default:
12059 break;
12060 }
12061 auto last_token = get_token_string();
12062 std::string message;
12063
12064 if (input_format != input_format_t::bjdata)
12065 {
12066 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12067 }
12068 else
12069 {
12070 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12071 }
12072 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12073 }
12074
12086 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12087 {
12088 result.first = npos; // size
12089 result.second = 0; // type
12090 bool is_ndarray = false;
12091
12092 get_ignore_noop();
12093
12094 if (current == '$')
12095 {
12096 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12097 if (input_format == input_format_t::bjdata
12098 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12099 {
12100 auto last_token = get_token_string();
12101 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12102 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12103 }
12104
12105 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12106 {
12107 return false;
12108 }
12109
12110 get_ignore_noop();
12111 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12112 {
12113 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12114 {
12115 return false;
12116 }
12117 auto last_token = get_token_string();
12118 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12119 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12120 }
12121
12122 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12123 if (input_format == input_format_t::bjdata && is_ndarray)
12124 {
12125 if (inside_ndarray)
12126 {
12127 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12128 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12129 }
12130 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12131 }
12132 return is_error;
12133 }
12134
12135 if (current == '#')
12136 {
12137 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12138 if (input_format == input_format_t::bjdata && is_ndarray)
12139 {
12140 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12141 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12142 }
12143 return is_error;
12144 }
12145
12146 return true;
12147 }
12148
12153 bool get_ubjson_value(const char_int_type prefix)
12154 {
12155 switch (prefix)
12156 {
12157 case char_traits<char_type>::eof(): // EOF
12158 return unexpect_eof(input_format, "value");
12159
12160 case 'T': // true
12161 return sax->boolean(true);
12162 case 'F': // false
12163 return sax->boolean(false);
12164
12165 case 'Z': // null
12166 return sax->null();
12167
12168 case 'B': // byte
12169 {
12170 if (input_format != input_format_t::bjdata)
12171 {
12172 break;
12173 }
12174 std::uint8_t number{};
12175 return get_number(input_format, number) && sax->number_unsigned(number);
12176 }
12177
12178 case 'U':
12179 {
12180 std::uint8_t number{};
12181 return get_number(input_format, number) && sax->number_unsigned(number);
12182 }
12183
12184 case 'i':
12185 {
12186 std::int8_t number{};
12187 return get_number(input_format, number) && sax->number_integer(number);
12188 }
12189
12190 case 'I':
12191 {
12192 std::int16_t number{};
12193 return get_number(input_format, number) && sax->number_integer(number);
12194 }
12195
12196 case 'l':
12197 {
12198 std::int32_t number{};
12199 return get_number(input_format, number) && sax->number_integer(number);
12200 }
12201
12202 case 'L':
12203 {
12204 std::int64_t number{};
12205 return get_number(input_format, number) && sax->number_integer(number);
12206 }
12207
12208 case 'u':
12209 {
12210 if (input_format != input_format_t::bjdata)
12211 {
12212 break;
12213 }
12214 std::uint16_t number{};
12215 return get_number(input_format, number) && sax->number_unsigned(number);
12216 }
12217
12218 case 'm':
12219 {
12220 if (input_format != input_format_t::bjdata)
12221 {
12222 break;
12223 }
12224 std::uint32_t number{};
12225 return get_number(input_format, number) && sax->number_unsigned(number);
12226 }
12227
12228 case 'M':
12229 {
12230 if (input_format != input_format_t::bjdata)
12231 {
12232 break;
12233 }
12234 std::uint64_t number{};
12235 return get_number(input_format, number) && sax->number_unsigned(number);
12236 }
12237
12238 case 'h':
12239 {
12240 if (input_format != input_format_t::bjdata)
12241 {
12242 break;
12243 }
12244 const auto byte1_raw = get();
12245 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12246 {
12247 return false;
12248 }
12249 const auto byte2_raw = get();
12250 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12251 {
12252 return false;
12253 }
12254
12255 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12256 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12257
12258 // Code from RFC 7049, Appendix D, Figure 3:
12259 // As half-precision floating-point numbers were only added
12260 // to IEEE 754 in 2008, today's programming platforms often
12261 // still only have limited support for them. It is very
12262 // easy to include at least decoding support for them even
12263 // without such support. An example of a small decoder for
12264 // half-precision floating-point numbers in the C language
12265 // is shown in Fig. 3.
12266 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12267 const double val = [&half]
12268 {
12269 const int exp = (half >> 10u) & 0x1Fu;
12270 const unsigned int mant = half & 0x3FFu;
12271 JSON_ASSERT(0 <= exp&& exp <= 32);
12272 JSON_ASSERT(mant <= 1024);
12273 switch (exp)
12274 {
12275 case 0:
12276 return std::ldexp(mant, -24);
12277 case 31:
12278 return (mant == 0)
12279 ? std::numeric_limits<double>::infinity()
12280 : std::numeric_limits<double>::quiet_NaN();
12281 default:
12282 return std::ldexp(mant + 1024, exp - 25);
12283 }
12284 }();
12285 return sax->number_float((half & 0x8000u) != 0
12286 ? static_cast<number_float_t>(-val)
12287 : static_cast<number_float_t>(val), "");
12288 }
12289
12290 case 'd':
12291 {
12292 float number{};
12293 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12294 }
12295
12296 case 'D':
12297 {
12298 double number{};
12299 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12300 }
12301
12302 case 'H':
12303 {
12304 return get_ubjson_high_precision_number();
12305 }
12306
12307 case 'C': // char
12308 {
12309 get();
12310 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12311 {
12312 return false;
12313 }
12314 if (JSON_HEDLEY_UNLIKELY(current > 127))
12315 {
12316 auto last_token = get_token_string();
12317 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12318 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12319 }
12320 string_t s(1, static_cast<typename string_t::value_type>(current));
12321 return sax->string(s);
12322 }
12323
12324 case 'S': // string
12325 {
12326 string_t s;
12327 return get_ubjson_string(s) && sax->string(s);
12328 }
12329
12330 case '[': // array
12331 return get_ubjson_array();
12332
12333 case '{': // object
12334 return get_ubjson_object();
12335
12336 default: // anything else
12337 break;
12338 }
12339 auto last_token = get_token_string();
12340 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));
12341 }
12342
12346 bool get_ubjson_array()
12347 {
12348 std::pair<std::size_t, char_int_type> size_and_type;
12349 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12350 {
12351 return false;
12352 }
12353
12354 // 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):
12355 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12356
12357 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12358 {
12359 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
12360 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)
12361 {
12362 return p.first < t;
12363 });
12364 string_t key = "_ArrayType_";
12365 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12366 {
12367 auto last_token = get_token_string();
12368 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12369 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12370 }
12371
12372 string_t type = it->second; // sax->string() takes a reference
12373 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12374 {
12375 return false;
12376 }
12377
12378 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12379 {
12380 size_and_type.second = 'U';
12381 }
12382
12383 key = "_ArrayData_";
12384 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12385 {
12386 return false;
12387 }
12388
12389 for (std::size_t i = 0; i < size_and_type.first; ++i)
12390 {
12391 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12392 {
12393 return false;
12394 }
12395 }
12396
12397 return (sax->end_array() && sax->end_object());
12398 }
12399
12400 // If BJData type marker is 'B' decode as binary
12401 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12402 {
12403 binary_t result;
12404 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12405 }
12406
12407 if (size_and_type.first != npos)
12408 {
12409 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12410 {
12411 return false;
12412 }
12413
12414 if (size_and_type.second != 0)
12415 {
12416 if (size_and_type.second != 'N')
12417 {
12418 for (std::size_t i = 0; i < size_and_type.first; ++i)
12419 {
12420 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12421 {
12422 return false;
12423 }
12424 }
12425 }
12426 }
12427 else
12428 {
12429 for (std::size_t i = 0; i < size_and_type.first; ++i)
12430 {
12431 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12432 {
12433 return false;
12434 }
12435 }
12436 }
12437 }
12438 else
12439 {
12440 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12441 {
12442 return false;
12443 }
12444
12445 while (current != ']')
12446 {
12447 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12448 {
12449 return false;
12450 }
12451 get_ignore_noop();
12452 }
12453 }
12454
12455 return sax->end_array();
12456 }
12457
12461 bool get_ubjson_object()
12462 {
12463 std::pair<std::size_t, char_int_type> size_and_type;
12464 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12465 {
12466 return false;
12467 }
12468
12469 // do not accept ND-array size in objects in BJData
12470 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12471 {
12472 auto last_token = get_token_string();
12473 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12474 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12475 }
12476
12477 string_t key;
12478 if (size_and_type.first != npos)
12479 {
12480 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12481 {
12482 return false;
12483 }
12484
12485 if (size_and_type.second != 0)
12486 {
12487 for (std::size_t i = 0; i < size_and_type.first; ++i)
12488 {
12489 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12490 {
12491 return false;
12492 }
12493 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12494 {
12495 return false;
12496 }
12497 key.clear();
12498 }
12499 }
12500 else
12501 {
12502 for (std::size_t i = 0; i < size_and_type.first; ++i)
12503 {
12504 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12505 {
12506 return false;
12507 }
12508 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12509 {
12510 return false;
12511 }
12512 key.clear();
12513 }
12514 }
12515 }
12516 else
12517 {
12518 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12519 {
12520 return false;
12521 }
12522
12523 while (current != '}')
12524 {
12525 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12526 {
12527 return false;
12528 }
12529 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12530 {
12531 return false;
12532 }
12533 get_ignore_noop();
12534 key.clear();
12535 }
12536 }
12537
12538 return sax->end_object();
12539 }
12540
12541 // Note, no reader for UBJSON binary types is implemented because they do
12542 // not exist
12543
12544 bool get_ubjson_high_precision_number()
12545 {
12546 // get the size of the following number string
12547 std::size_t size{};
12548 bool no_ndarray = true;
12549 auto res = get_ubjson_size_value(size, no_ndarray);
12550 if (JSON_HEDLEY_UNLIKELY(!res))
12551 {
12552 return res;
12553 }
12554
12555 // get number string
12556 std::vector<char> number_vector;
12557 for (std::size_t i = 0; i < size; ++i)
12558 {
12559 get();
12560 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12561 {
12562 return false;
12563 }
12564 number_vector.push_back(static_cast<char>(current));
12565 }
12566
12567 // parse number string
12568 using ia_type = decltype(detail::input_adapter(number_vector));
12569 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12570 const auto result_number = number_lexer.scan();
12571 const auto number_string = number_lexer.get_token_string();
12572 const auto result_remainder = number_lexer.scan();
12573
12574 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12575
12576 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12577 {
12578 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12579 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12580 }
12581
12582 switch (result_number)
12583 {
12584 case token_type::value_integer:
12585 return sax->number_integer(number_lexer.get_number_integer());
12586 case token_type::value_unsigned:
12587 return sax->number_unsigned(number_lexer.get_number_unsigned());
12588 case token_type::value_float:
12589 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12590 case token_type::uninitialized:
12591 case token_type::literal_true:
12592 case token_type::literal_false:
12593 case token_type::literal_null:
12594 case token_type::value_string:
12595 case token_type::begin_array:
12596 case token_type::begin_object:
12597 case token_type::end_array:
12598 case token_type::end_object:
12599 case token_type::name_separator:
12600 case token_type::value_separator:
12601 case token_type::parse_error:
12602 case token_type::end_of_input:
12603 case token_type::literal_or_value:
12604 default:
12605 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12606 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12607 }
12608 }
12609
12611 // Utility functions //
12613
12623 char_int_type get()
12624 {
12625 ++chars_read;
12626 return current = ia.get_character();
12627 }
12628
12637 template<class T>
12638 bool get_to(T& dest, const input_format_t format, const char* context)
12639 {
12640 auto new_chars_read = ia.get_elements(&dest);
12641 chars_read += new_chars_read;
12642 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12643 {
12644 // in case of failure, advance position by 1 to report the failing location
12645 ++chars_read;
12646 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12647 return false;
12648 }
12649 return true;
12650 }
12651
12655 char_int_type get_ignore_noop()
12656 {
12657 do
12658 {
12659 get();
12660 }
12661 while (current == 'N');
12662
12663 return current;
12664 }
12665
12666 template<class NumberType>
12667 static void byte_swap(NumberType& number)
12668 {
12669 constexpr std::size_t sz = sizeof(number);
12670#ifdef __cpp_lib_byteswap
12671 if constexpr (sz == 1)
12672 {
12673 return;
12674 }
12675 else if constexpr(std::is_integral_v<NumberType>)
12676 {
12677 number = std::byteswap(number);
12678 return;
12679 }
12680 else
12681 {
12682#endif
12683 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12684 for (std::size_t i = 0; i < sz / 2; ++i)
12685 {
12686 std::swap(ptr[i], ptr[sz - i - 1]);
12687 }
12688#ifdef __cpp_lib_byteswap
12689 }
12690#endif
12691 }
12692
12693 /*
12694 @brief read a number from the input
12695
12696 @tparam NumberType the type of the number
12697 @param[in] format the current format (for diagnostics)
12698 @param[out] result number of type @a NumberType
12699
12700 @return whether conversion completed
12701
12702 @note This function needs to respect the system's endianness, because
12703 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12704 (big endian) and therefore need reordering on little endian systems.
12705 On the other hand, BSON and BJData use little endian and should reorder
12706 on big endian systems.
12707 */
12708 template<typename NumberType, bool InputIsLittleEndian = false>
12709 bool get_number(const input_format_t format, NumberType& result)
12710 {
12711 // read in the original format
12712
12713 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12714 {
12715 return false;
12716 }
12717 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12718 {
12719 byte_swap(result);
12720 }
12721 return true;
12722 }
12723
12738 template<typename NumberType>
12739 bool get_string(const input_format_t format,
12740 const NumberType len,
12741 string_t& result)
12742 {
12743 bool success = true;
12744 for (NumberType i = 0; i < len; i++)
12745 {
12746 get();
12747 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12748 {
12749 success = false;
12750 break;
12751 }
12752 result.push_back(static_cast<typename string_t::value_type>(current));
12753 }
12754 return success;
12755 }
12756
12771 template<typename NumberType>
12772 bool get_binary(const input_format_t format,
12773 const NumberType len,
12774 binary_t& result)
12775 {
12776 bool success = true;
12777 for (NumberType i = 0; i < len; i++)
12778 {
12779 get();
12780 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12781 {
12782 success = false;
12783 break;
12784 }
12785 result.push_back(static_cast<typename binary_t::value_type>(current));
12786 }
12787 return success;
12788 }
12789
12795 JSON_HEDLEY_NON_NULL(3)
12796 bool unexpect_eof(const input_format_t format, const char* context) const
12797 {
12798 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12799 {
12800 return sax->parse_error(chars_read, "<end of file>",
12801 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12802 }
12803 return true;
12804 }
12805
12809 std::string get_token_string() const
12810 {
12811 std::array<char, 3> cr{{}};
12812 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12813 return std::string{cr.data()};
12814 }
12815
12822 std::string exception_message(const input_format_t format,
12823 const std::string& detail,
12824 const std::string& context) const
12825 {
12826 std::string error_msg = "syntax error while parsing ";
12827
12828 switch (format)
12829 {
12830 case input_format_t::cbor:
12831 error_msg += "CBOR";
12832 break;
12833
12834 case input_format_t::msgpack:
12835 error_msg += "MessagePack";
12836 break;
12837
12838 case input_format_t::ubjson:
12839 error_msg += "UBJSON";
12840 break;
12841
12842 case input_format_t::bson:
12843 error_msg += "BSON";
12844 break;
12845
12846 case input_format_t::bjdata:
12847 error_msg += "BJData";
12848 break;
12849
12850 case input_format_t::json: // LCOV_EXCL_LINE
12851 default: // LCOV_EXCL_LINE
12852 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12853 }
12854
12855 return concat(error_msg, ' ', context, ": ", detail);
12856 }
12857
12858 private:
12859 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12860
12862 InputAdapterType ia;
12863
12865 char_int_type current = char_traits<char_type>::eof();
12866
12868 std::size_t chars_read = 0;
12869
12871 const bool is_little_endian = little_endianness();
12872
12874 const input_format_t input_format = input_format_t::json;
12875
12877 json_sax_t* sax = nullptr;
12878
12879 // excluded markers in bjdata optimized type
12880#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12881 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12882
12883#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12884 make_array<bjd_type>( \
12885 bjd_type{'B', "byte"}, \
12886 bjd_type{'C', "char"}, \
12887 bjd_type{'D', "double"}, \
12888 bjd_type{'I', "int16"}, \
12889 bjd_type{'L', "int64"}, \
12890 bjd_type{'M', "uint64"}, \
12891 bjd_type{'U', "uint8"}, \
12892 bjd_type{'d', "single"}, \
12893 bjd_type{'i', "int8"}, \
12894 bjd_type{'l', "int32"}, \
12895 bjd_type{'m', "uint32"}, \
12896 bjd_type{'u', "uint16"})
12897
12898 JSON_PRIVATE_UNLESS_TESTED:
12899 // lookup tables
12900 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12901 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12902 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12903
12904 using bjd_type = std::pair<char_int_type, string_t>;
12905 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12906 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12907 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12908
12909#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12910#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12911};
12912
12913#ifndef JSON_HAS_CPP_17
12914 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12915 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12916#endif
12917
12918} // namespace detail
12919NLOHMANN_JSON_NAMESPACE_END
12920
12921// #include <nlohmann/detail/input/input_adapters.hpp>
12922
12923// #include <nlohmann/detail/input/lexer.hpp>
12924
12925// #include <nlohmann/detail/input/parser.hpp>
12926// __ _____ _____ _____
12927// __| | __| | | | JSON for Modern C++
12928// | | |__ | | | | | | version 3.12.0
12929// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12930//
12931// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
12932// SPDX-License-Identifier: MIT
12933
12934
12935
12936#include <cmath> // isfinite
12937#include <cstdint> // uint8_t
12938#include <functional> // function
12939#include <string> // string
12940#include <utility> // move
12941#include <vector> // vector
12942
12943// #include <nlohmann/detail/exceptions.hpp>
12944
12945// #include <nlohmann/detail/input/input_adapters.hpp>
12946
12947// #include <nlohmann/detail/input/json_sax.hpp>
12948
12949// #include <nlohmann/detail/input/lexer.hpp>
12950
12951// #include <nlohmann/detail/macro_scope.hpp>
12952
12953// #include <nlohmann/detail/meta/is_sax.hpp>
12954
12955// #include <nlohmann/detail/string_concat.hpp>
12956
12957// #include <nlohmann/detail/value_t.hpp>
12958
12959
12960NLOHMANN_JSON_NAMESPACE_BEGIN
12961namespace detail
12962{
12964// parser //
12966
12967enum class parse_event_t : std::uint8_t
12968{
12980 value
12981};
12982
12983template<typename BasicJsonType>
12984using parser_callback_t =
12985 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12986
12992template<typename BasicJsonType, typename InputAdapterType>
12994{
12995 using number_integer_t = typename BasicJsonType::number_integer_t;
12996 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12997 using number_float_t = typename BasicJsonType::number_float_t;
12998 using string_t = typename BasicJsonType::string_t;
13000 using token_type = typename lexer_t::token_type;
13001
13002 public:
13004 explicit parser(InputAdapterType&& adapter,
13005 parser_callback_t<BasicJsonType> cb = nullptr,
13006 const bool allow_exceptions_ = true,
13007 const bool ignore_comments = false,
13008 const bool ignore_trailing_commas_ = false)
13009 : callback(std::move(cb))
13010 , m_lexer(std::move(adapter), ignore_comments)
13011 , allow_exceptions(allow_exceptions_)
13012 , ignore_trailing_commas(ignore_trailing_commas_)
13013 {
13014 // read first token
13015 get_token();
13016 }
13017
13028 void parse(const bool strict, BasicJsonType& result)
13029 {
13030 if (callback)
13031 {
13032 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13033 sax_parse_internal(&sdp);
13034
13035 // in strict mode, input must be completely read
13036 if (strict && (get_token() != token_type::end_of_input))
13037 {
13038 sdp.parse_error(m_lexer.get_position(),
13039 m_lexer.get_token_string(),
13040 parse_error::create(101, m_lexer.get_position(),
13041 exception_message(token_type::end_of_input, "value"), nullptr));
13042 }
13043
13044 // in case of an error, return a discarded value
13045 if (sdp.is_errored())
13046 {
13047 result = value_t::discarded;
13048 return;
13049 }
13050
13051 // set top-level value to null if it was discarded by the callback
13052 // function
13053 if (result.is_discarded())
13054 {
13055 result = nullptr;
13056 }
13057 }
13058 else
13059 {
13060 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13061 sax_parse_internal(&sdp);
13062
13063 // in strict mode, input must be completely read
13064 if (strict && (get_token() != token_type::end_of_input))
13065 {
13066 sdp.parse_error(m_lexer.get_position(),
13067 m_lexer.get_token_string(),
13068 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13069 }
13070
13071 // in case of an error, return a discarded value
13072 if (sdp.is_errored())
13073 {
13074 result = value_t::discarded;
13075 return;
13076 }
13077 }
13078
13079 result.assert_invariant();
13080 }
13081
13088 bool accept(const bool strict = true)
13089 {
13091 return sax_parse(&sax_acceptor, strict);
13092 }
13093
13094 template<typename SAX>
13095 JSON_HEDLEY_NON_NULL(2)
13096 bool sax_parse(SAX* sax, const bool strict = true)
13097 {
13099 const bool result = sax_parse_internal(sax);
13100
13101 // strict mode: next byte must be EOF
13102 if (result && strict && (get_token() != token_type::end_of_input))
13103 {
13104 return sax->parse_error(m_lexer.get_position(),
13105 m_lexer.get_token_string(),
13106 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13107 }
13108
13109 return result;
13110 }
13111
13112 private:
13113 template<typename SAX>
13114 JSON_HEDLEY_NON_NULL(2)
13115 bool sax_parse_internal(SAX* sax)
13116 {
13117 // stack to remember the hierarchy of structured values we are parsing
13118 // true = array; false = object
13119 std::vector<bool> states;
13120 // value to avoid a goto (see comment where set to true)
13121 bool skip_to_state_evaluation = false;
13122
13123 while (true)
13124 {
13125 if (!skip_to_state_evaluation)
13126 {
13127 // invariant: get_token() was called before each iteration
13128 switch (last_token)
13129 {
13130 case token_type::begin_object:
13131 {
13132 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13133 {
13134 return false;
13135 }
13136
13137 // closing } -> we are done
13138 if (get_token() == token_type::end_object)
13139 {
13140 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13141 {
13142 return false;
13143 }
13144 break;
13145 }
13146
13147 // parse key
13148 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13149 {
13150 return sax->parse_error(m_lexer.get_position(),
13151 m_lexer.get_token_string(),
13152 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13153 }
13154 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13155 {
13156 return false;
13157 }
13158
13159 // parse separator (:)
13160 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13161 {
13162 return sax->parse_error(m_lexer.get_position(),
13163 m_lexer.get_token_string(),
13164 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13165 }
13166
13167 // remember we are now inside an object
13168 states.push_back(false);
13169
13170 // parse values
13171 get_token();
13172 continue;
13173 }
13174
13175 case token_type::begin_array:
13176 {
13177 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13178 {
13179 return false;
13180 }
13181
13182 // closing ] -> we are done
13183 if (get_token() == token_type::end_array)
13184 {
13185 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13186 {
13187 return false;
13188 }
13189 break;
13190 }
13191
13192 // remember we are now inside an array
13193 states.push_back(true);
13194
13195 // parse values (no need to call get_token)
13196 continue;
13197 }
13198
13199 case token_type::value_float:
13200 {
13201 const auto res = m_lexer.get_number_float();
13202
13203 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13204 {
13205 return sax->parse_error(m_lexer.get_position(),
13206 m_lexer.get_token_string(),
13207 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13208 }
13209
13210 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13211 {
13212 return false;
13213 }
13214
13215 break;
13216 }
13217
13218 case token_type::literal_false:
13219 {
13220 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13221 {
13222 return false;
13223 }
13224 break;
13225 }
13226
13227 case token_type::literal_null:
13228 {
13229 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13230 {
13231 return false;
13232 }
13233 break;
13234 }
13235
13236 case token_type::literal_true:
13237 {
13238 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13239 {
13240 return false;
13241 }
13242 break;
13243 }
13244
13245 case token_type::value_integer:
13246 {
13247 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13248 {
13249 return false;
13250 }
13251 break;
13252 }
13253
13254 case token_type::value_string:
13255 {
13256 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13257 {
13258 return false;
13259 }
13260 break;
13261 }
13262
13263 case token_type::value_unsigned:
13264 {
13265 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13266 {
13267 return false;
13268 }
13269 break;
13270 }
13271
13272 case token_type::parse_error:
13273 {
13274 // using "uninitialized" to avoid an "expected" message
13275 return sax->parse_error(m_lexer.get_position(),
13276 m_lexer.get_token_string(),
13277 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13278 }
13279 case token_type::end_of_input:
13280 {
13281 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
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(),
13286 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13287 }
13288
13289 return sax->parse_error(m_lexer.get_position(),
13290 m_lexer.get_token_string(),
13291 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13292 }
13293 case token_type::uninitialized:
13294 case token_type::end_array:
13295 case token_type::end_object:
13296 case token_type::name_separator:
13297 case token_type::value_separator:
13298 case token_type::literal_or_value:
13299 default: // the last token was unexpected
13300 {
13301 return sax->parse_error(m_lexer.get_position(),
13302 m_lexer.get_token_string(),
13303 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13304 }
13305 }
13306 }
13307 else
13308 {
13309 skip_to_state_evaluation = false;
13310 }
13311
13312 // we reached this line after we successfully parsed a value
13313 if (states.empty())
13314 {
13315 // empty stack: we reached the end of the hierarchy: done
13316 return true;
13317 }
13318
13319 if (states.back()) // array
13320 {
13321 // comma -> next value
13322 // or end of array (ignore_trailing_commas = true)
13323 if (get_token() == token_type::value_separator)
13324 {
13325 // parse a new value
13326 get_token();
13327
13328 // if ignore_trailing_commas and last_token is ], we can continue to "closing ]"
13329 if (!(ignore_trailing_commas && last_token == token_type::end_array))
13330 {
13331 continue;
13332 }
13333 }
13334
13335 // closing ]
13336 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13337 {
13338 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13339 {
13340 return false;
13341 }
13342
13343 // We are done with this array. Before we can parse a
13344 // new value, we need to evaluate the new state first.
13345 // By setting skip_to_state_evaluation to false, we
13346 // are effectively jumping to the beginning of this if.
13347 JSON_ASSERT(!states.empty());
13348 states.pop_back();
13349 skip_to_state_evaluation = true;
13350 continue;
13351 }
13352
13353 return sax->parse_error(m_lexer.get_position(),
13354 m_lexer.get_token_string(),
13355 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13356 }
13357
13358 // states.back() is false -> object
13359
13360 // comma -> next value
13361 // or end of object (ignore_trailing_commas = true)
13362 if (get_token() == token_type::value_separator)
13363 {
13364 get_token();
13365
13366 // if ignore_trailing_commas and last_token is }, we can continue to "closing }"
13367 if (!(ignore_trailing_commas && last_token == token_type::end_object))
13368 {
13369 // parse key
13370 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13371 {
13372 return sax->parse_error(m_lexer.get_position(),
13373 m_lexer.get_token_string(),
13374 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13375 }
13376
13377 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13378 {
13379 return false;
13380 }
13381
13382 // parse separator (:)
13383 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13384 {
13385 return sax->parse_error(m_lexer.get_position(),
13386 m_lexer.get_token_string(),
13387 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13388 }
13389
13390 // parse values
13391 get_token();
13392 continue;
13393 }
13394 }
13395
13396 // closing }
13397 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13398 {
13399 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13400 {
13401 return false;
13402 }
13403
13404 // We are done with this object. Before we can parse a
13405 // new value, we need to evaluate the new state first.
13406 // By setting skip_to_state_evaluation to false, we
13407 // are effectively jumping to the beginning of this if.
13408 JSON_ASSERT(!states.empty());
13409 states.pop_back();
13410 skip_to_state_evaluation = true;
13411 continue;
13412 }
13413
13414 return sax->parse_error(m_lexer.get_position(),
13415 m_lexer.get_token_string(),
13416 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13417 }
13418 }
13419
13421 token_type get_token()
13422 {
13423 return last_token = m_lexer.scan();
13424 }
13425
13426 std::string exception_message(const token_type expected, const std::string& context)
13427 {
13428 std::string error_msg = "syntax error ";
13429
13430 if (!context.empty())
13431 {
13432 error_msg += concat("while parsing ", context, ' ');
13433 }
13434
13435 error_msg += "- ";
13436
13437 if (last_token == token_type::parse_error)
13438 {
13439 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13440 m_lexer.get_token_string(), '\'');
13441 }
13442 else
13443 {
13444 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13445 }
13446
13447 if (expected != token_type::uninitialized)
13448 {
13449 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13450 }
13451
13452 return error_msg;
13453 }
13454
13455 private:
13457 const parser_callback_t<BasicJsonType> callback = nullptr;
13459 token_type last_token = token_type::uninitialized;
13461 lexer_t m_lexer;
13463 const bool allow_exceptions = true;
13465 const bool ignore_trailing_commas = false;
13466};
13467
13468} // namespace detail
13469NLOHMANN_JSON_NAMESPACE_END
13470
13471// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13472// __ _____ _____ _____
13473// __| | __| | | | JSON for Modern C++
13474// | | |__ | | | | | | version 3.12.0
13475// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13476//
13477// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
13478// SPDX-License-Identifier: MIT
13479
13480
13481
13482// #include <nlohmann/detail/abi_macros.hpp>
13483
13484// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13485// __ _____ _____ _____
13486// __| | __| | | | JSON for Modern C++
13487// | | |__ | | | | | | version 3.12.0
13488// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13489//
13490// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
13491// SPDX-License-Identifier: MIT
13492
13493
13494
13495#include <cstddef> // ptrdiff_t
13496#include <limits> // numeric_limits
13497
13498// #include <nlohmann/detail/macro_scope.hpp>
13499
13500
13501NLOHMANN_JSON_NAMESPACE_BEGIN
13502namespace detail
13503{
13504
13505/*
13506@brief an iterator for primitive JSON types
13507
13508This class models an iterator for primitive JSON types (boolean, number,
13509string). Its only purpose is to allow the iterator/const_iterator classes
13510to "iterate" over primitive values. Internally, the iterator is modeled by
13511a `difference_type` variable. Value begin_value (`0`) models the begin and
13512end_value (`1`) models past the end.
13513*/
13515{
13516 private:
13517 using difference_type = std::ptrdiff_t;
13518 static constexpr difference_type begin_value = 0;
13519 static constexpr difference_type end_value = begin_value + 1;
13520
13521 JSON_PRIVATE_UNLESS_TESTED:
13523 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13524
13525 public:
13526 constexpr difference_type get_value() const noexcept
13527 {
13528 return m_it;
13529 }
13530
13532 void set_begin() noexcept
13533 {
13534 m_it = begin_value;
13535 }
13536
13538 void set_end() noexcept
13539 {
13540 m_it = end_value;
13541 }
13542
13544 constexpr bool is_begin() const noexcept
13545 {
13546 return m_it == begin_value;
13547 }
13548
13550 constexpr bool is_end() const noexcept
13551 {
13552 return m_it == end_value;
13553 }
13554
13555 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13556 {
13557 return lhs.m_it == rhs.m_it;
13558 }
13559
13560 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13561 {
13562 return lhs.m_it < rhs.m_it;
13563 }
13564
13565 primitive_iterator_t operator+(difference_type n) noexcept
13566 {
13567 auto result = *this;
13568 result += n;
13569 return result;
13570 }
13571
13572 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13573 {
13574 return lhs.m_it - rhs.m_it;
13575 }
13576
13577 primitive_iterator_t& operator++() noexcept
13578 {
13579 ++m_it;
13580 return *this;
13581 }
13582
13583 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13584 {
13585 auto result = *this;
13586 ++m_it;
13587 return result;
13588 }
13589
13590 primitive_iterator_t& operator--() noexcept
13591 {
13592 --m_it;
13593 return *this;
13594 }
13595
13596 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13597 {
13598 auto result = *this;
13599 --m_it;
13600 return result;
13601 }
13602
13603 primitive_iterator_t& operator+=(difference_type n) noexcept
13604 {
13605 m_it += n;
13606 return *this;
13607 }
13608
13609 primitive_iterator_t& operator-=(difference_type n) noexcept
13610 {
13611 m_it -= n;
13612 return *this;
13613 }
13614};
13615
13616} // namespace detail
13617NLOHMANN_JSON_NAMESPACE_END
13618
13619
13620NLOHMANN_JSON_NAMESPACE_BEGIN
13621namespace detail
13622{
13623
13630template<typename BasicJsonType> struct internal_iterator
13631{
13633 typename BasicJsonType::object_t::iterator object_iterator {};
13635 typename BasicJsonType::array_t::iterator array_iterator {};
13638};
13639
13640} // namespace detail
13641NLOHMANN_JSON_NAMESPACE_END
13642
13643// #include <nlohmann/detail/iterators/iter_impl.hpp>
13644// __ _____ _____ _____
13645// __| | __| | | | JSON for Modern C++
13646// | | |__ | | | | | | version 3.12.0
13647// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13648//
13649// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
13650// SPDX-License-Identifier: MIT
13651
13652
13653
13654#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13655#include <type_traits> // conditional, is_const, remove_const
13656
13657// #include <nlohmann/detail/exceptions.hpp>
13658
13659// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13660
13661// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13662
13663// #include <nlohmann/detail/macro_scope.hpp>
13664
13665// #include <nlohmann/detail/meta/cpp_future.hpp>
13666
13667// #include <nlohmann/detail/meta/type_traits.hpp>
13668
13669// #include <nlohmann/detail/value_t.hpp>
13670
13671
13672NLOHMANN_JSON_NAMESPACE_BEGIN
13673namespace detail
13674{
13675
13676// forward declare to be able to friend it later on
13677template<typename IteratorType> class iteration_proxy;
13678template<typename IteratorType> class iteration_proxy_value;
13679
13696template<typename BasicJsonType>
13697class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13698{
13700 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13702 friend other_iter_impl;
13703 friend BasicJsonType;
13706
13707 using object_t = typename BasicJsonType::object_t;
13708 using array_t = typename BasicJsonType::array_t;
13709 // make sure BasicJsonType is basic_json or const basic_json
13711 "iter_impl only accepts (const) basic_json");
13712 // superficial check for the LegacyBidirectionalIterator named requirement
13713 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13714 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13715 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13716
13717 public:
13723 using iterator_category = std::bidirectional_iterator_tag;
13724
13726 using value_type = typename BasicJsonType::value_type;
13728 using difference_type = typename BasicJsonType::difference_type;
13730 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13731 typename BasicJsonType::const_pointer,
13732 typename BasicJsonType::pointer>::type;
13735 typename std::conditional<std::is_const<BasicJsonType>::value,
13736 typename BasicJsonType::const_reference,
13737 typename BasicJsonType::reference>::type;
13738
13739 iter_impl() = default;
13740 ~iter_impl() = default;
13741 iter_impl(iter_impl&&) noexcept = default;
13742 iter_impl& operator=(iter_impl&&) noexcept = default;
13743
13750 explicit iter_impl(pointer object) noexcept : m_object(object)
13751 {
13752 JSON_ASSERT(m_object != nullptr);
13753
13754 switch (m_object->m_data.m_type)
13755 {
13756 case value_t::object:
13757 {
13758 m_it.object_iterator = typename object_t::iterator();
13759 break;
13760 }
13761
13762 case value_t::array:
13763 {
13764 m_it.array_iterator = typename array_t::iterator();
13765 break;
13766 }
13767
13768 case value_t::null:
13769 case value_t::string:
13770 case value_t::boolean:
13774 case value_t::binary:
13775 case value_t::discarded:
13776 default:
13777 {
13778 m_it.primitive_iterator = primitive_iterator_t();
13779 break;
13780 }
13781 }
13782 }
13783
13792
13800 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13801 : m_object(other.m_object), m_it(other.m_it)
13802 {}
13803
13810 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
13811 {
13812 if (&other != this)
13813 {
13814 m_object = other.m_object;
13815 m_it = other.m_it;
13816 }
13817 return *this;
13818 }
13819
13825 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13826 : m_object(other.m_object), m_it(other.m_it)
13827 {}
13828
13835 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13836 {
13837 m_object = other.m_object;
13838 m_it = other.m_it;
13839 return *this;
13840 }
13841
13842 JSON_PRIVATE_UNLESS_TESTED:
13847 void set_begin() noexcept
13848 {
13849 JSON_ASSERT(m_object != nullptr);
13850
13851 switch (m_object->m_data.m_type)
13852 {
13853 case value_t::object:
13854 {
13855 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13856 break;
13857 }
13858
13859 case value_t::array:
13860 {
13861 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13862 break;
13863 }
13864
13865 case value_t::null:
13866 {
13867 // set to end so begin()==end() is true: null is empty
13868 m_it.primitive_iterator.set_end();
13869 break;
13870 }
13871
13872 case value_t::string:
13873 case value_t::boolean:
13874 case value_t::number_integer:
13875 case value_t::number_unsigned:
13876 case value_t::number_float:
13877 case value_t::binary:
13878 case value_t::discarded:
13879 default:
13880 {
13881 m_it.primitive_iterator.set_begin();
13882 break;
13883 }
13884 }
13885 }
13886
13891 void set_end() noexcept
13892 {
13893 JSON_ASSERT(m_object != nullptr);
13894
13895 switch (m_object->m_data.m_type)
13896 {
13897 case value_t::object:
13898 {
13899 m_it.object_iterator = m_object->m_data.m_value.object->end();
13900 break;
13901 }
13902
13903 case value_t::array:
13904 {
13905 m_it.array_iterator = m_object->m_data.m_value.array->end();
13906 break;
13907 }
13908
13909 case value_t::null:
13910 case value_t::string:
13911 case value_t::boolean:
13915 case value_t::binary:
13916 case value_t::discarded:
13917 default:
13918 {
13919 m_it.primitive_iterator.set_end();
13920 break;
13921 }
13922 }
13923 }
13924
13925 public:
13931 {
13932 JSON_ASSERT(m_object != nullptr);
13933
13934 switch (m_object->m_data.m_type)
13935 {
13936 case value_t::object:
13937 {
13938 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13939 return m_it.object_iterator->second;
13940 }
13941
13942 case value_t::array:
13943 {
13944 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13945 return *m_it.array_iterator;
13946 }
13947
13948 case value_t::null:
13949 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13950
13951 case value_t::string:
13952 case value_t::boolean:
13956 case value_t::binary:
13957 case value_t::discarded:
13958 default:
13959 {
13960 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13961 {
13962 return *m_object;
13963 }
13964
13965 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13966 }
13967 }
13968 }
13969
13975 {
13976 JSON_ASSERT(m_object != nullptr);
13977
13978 switch (m_object->m_data.m_type)
13979 {
13980 case value_t::object:
13981 {
13982 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13983 return &(m_it.object_iterator->second);
13984 }
13985
13986 case value_t::array:
13987 {
13988 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13989 return &*m_it.array_iterator;
13990 }
13991
13992 case value_t::null:
13993 case value_t::string:
13994 case value_t::boolean:
13998 case value_t::binary:
13999 case value_t::discarded:
14000 default:
14001 {
14002 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
14003 {
14004 return m_object;
14005 }
14006
14007 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14008 }
14009 }
14010 }
14011
14016 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
14017 {
14018 auto result = *this;
14019 ++(*this);
14020 return result;
14021 }
14022
14027 iter_impl& operator++()
14028 {
14029 JSON_ASSERT(m_object != nullptr);
14030
14031 switch (m_object->m_data.m_type)
14032 {
14033 case value_t::object:
14034 {
14035 std::advance(m_it.object_iterator, 1);
14036 break;
14037 }
14038
14039 case value_t::array:
14040 {
14041 std::advance(m_it.array_iterator, 1);
14042 break;
14043 }
14044
14045 case value_t::null:
14046 case value_t::string:
14047 case value_t::boolean:
14051 case value_t::binary:
14052 case value_t::discarded:
14053 default:
14054 {
14055 ++m_it.primitive_iterator;
14056 break;
14057 }
14058 }
14059
14060 return *this;
14061 }
14062
14067 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14068 {
14069 auto result = *this;
14070 --(*this);
14071 return result;
14072 }
14073
14078 iter_impl& operator--()
14079 {
14080 JSON_ASSERT(m_object != nullptr);
14081
14082 switch (m_object->m_data.m_type)
14083 {
14084 case value_t::object:
14085 {
14086 std::advance(m_it.object_iterator, -1);
14087 break;
14088 }
14089
14090 case value_t::array:
14091 {
14092 std::advance(m_it.array_iterator, -1);
14093 break;
14094 }
14095
14096 case value_t::null:
14097 case value_t::string:
14098 case value_t::boolean:
14102 case value_t::binary:
14103 case value_t::discarded:
14104 default:
14105 {
14106 --m_it.primitive_iterator;
14107 break;
14108 }
14109 }
14110
14111 return *this;
14112 }
14113
14118 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 >
14119 bool operator==(const IterImpl& other) const
14120 {
14121 // if objects are not the same, the comparison is undefined
14122 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14123 {
14124 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14125 }
14126
14127 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14128 if (m_object == nullptr)
14129 {
14130 return true;
14131 }
14132
14133 switch (m_object->m_data.m_type)
14134 {
14135 case value_t::object:
14136 return (m_it.object_iterator == other.m_it.object_iterator);
14137
14138 case value_t::array:
14139 return (m_it.array_iterator == other.m_it.array_iterator);
14140
14141 case value_t::null:
14142 case value_t::string:
14143 case value_t::boolean:
14147 case value_t::binary:
14148 case value_t::discarded:
14149 default:
14150 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14151 }
14152 }
14153
14158 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 >
14159 bool operator!=(const IterImpl& other) const
14160 {
14161 return !operator==(other);
14162 }
14163
14168 bool operator<(const iter_impl& other) const
14169 {
14170 // if objects are not the same, the comparison is undefined
14171 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14172 {
14173 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14174 }
14175
14176 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14177 if (m_object == nullptr)
14178 {
14179 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14180 return false;
14181 }
14182
14183 switch (m_object->m_data.m_type)
14184 {
14185 case value_t::object:
14186 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14187
14188 case value_t::array:
14189 return (m_it.array_iterator < other.m_it.array_iterator);
14190
14191 case value_t::null:
14192 case value_t::string:
14193 case value_t::boolean:
14197 case value_t::binary:
14198 case value_t::discarded:
14199 default:
14200 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14201 }
14202 }
14203
14208 bool operator<=(const iter_impl& other) const
14209 {
14210 return !other.operator < (*this);
14211 }
14212
14217 bool operator>(const iter_impl& other) const
14218 {
14219 return !operator<=(other);
14220 }
14221
14226 bool operator>=(const iter_impl& other) const
14227 {
14228 return !operator<(other);
14229 }
14230
14236 {
14237 JSON_ASSERT(m_object != nullptr);
14238
14239 switch (m_object->m_data.m_type)
14240 {
14241 case value_t::object:
14242 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14243
14244 case value_t::array:
14245 {
14246 std::advance(m_it.array_iterator, i);
14247 break;
14248 }
14249
14250 case value_t::null:
14251 case value_t::string:
14252 case value_t::boolean:
14256 case value_t::binary:
14257 case value_t::discarded:
14258 default:
14259 {
14260 m_it.primitive_iterator += i;
14261 break;
14262 }
14263 }
14264
14265 return *this;
14266 }
14267
14273 {
14274 return operator+=(-i);
14275 }
14276
14281 iter_impl operator+(difference_type i) const
14282 {
14283 auto result = *this;
14284 result += i;
14285 return result;
14286 }
14287
14292 friend iter_impl operator+(difference_type i, const iter_impl& it)
14293 {
14294 auto result = it;
14295 result += i;
14296 return result;
14297 }
14298
14303 iter_impl operator-(difference_type i) const
14304 {
14305 auto result = *this;
14306 result -= i;
14307 return result;
14308 }
14309
14314 difference_type operator-(const iter_impl& other) const
14315 {
14316 JSON_ASSERT(m_object != nullptr);
14317
14318 switch (m_object->m_data.m_type)
14319 {
14320 case value_t::object:
14321 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14322
14323 case value_t::array:
14324 return m_it.array_iterator - other.m_it.array_iterator;
14325
14326 case value_t::null:
14327 case value_t::string:
14328 case value_t::boolean:
14332 case value_t::binary:
14333 case value_t::discarded:
14334 default:
14335 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14336 }
14337 }
14338
14344 {
14345 JSON_ASSERT(m_object != nullptr);
14346
14347 switch (m_object->m_data.m_type)
14348 {
14349 case value_t::object:
14350 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14351
14352 case value_t::array:
14353 return *std::next(m_it.array_iterator, n);
14354
14355 case value_t::null:
14356 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14357
14358 case value_t::string:
14359 case value_t::boolean:
14363 case value_t::binary:
14364 case value_t::discarded:
14365 default:
14366 {
14367 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14368 {
14369 return *m_object;
14370 }
14371
14372 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14373 }
14374 }
14375 }
14376
14381 const typename object_t::key_type& key() const
14382 {
14383 JSON_ASSERT(m_object != nullptr);
14384
14385 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14386 {
14387 return m_it.object_iterator->first;
14388 }
14389
14390 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14391 }
14392
14398 {
14399 return operator*();
14400 }
14401
14402 JSON_PRIVATE_UNLESS_TESTED:
14404 pointer m_object = nullptr;
14407};
14408
14409} // namespace detail
14410NLOHMANN_JSON_NAMESPACE_END
14411
14412// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14413
14414// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14415// __ _____ _____ _____
14416// __| | __| | | | JSON for Modern C++
14417// | | |__ | | | | | | version 3.12.0
14418// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14419//
14420// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
14421// SPDX-License-Identifier: MIT
14422
14423
14424
14425#include <cstddef> // ptrdiff_t
14426#include <iterator> // reverse_iterator
14427#include <utility> // declval
14428
14429// #include <nlohmann/detail/abi_macros.hpp>
14430
14431
14432NLOHMANN_JSON_NAMESPACE_BEGIN
14433namespace detail
14434{
14435
14437// reverse_iterator //
14439
14458template<typename Base>
14459class json_reverse_iterator : public std::reverse_iterator<Base>
14460{
14461 public:
14462 using difference_type = std::ptrdiff_t;
14464 using base_iterator = std::reverse_iterator<Base>;
14466 using reference = typename Base::reference;
14467
14469 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14470 : base_iterator(it) {}
14471
14473 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14474
14476 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14477 {
14478 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14479 }
14480
14483 {
14484 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14485 }
14486
14488 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14489 {
14490 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14491 }
14492
14495 {
14496 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14497 }
14498
14501 {
14502 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14503 }
14504
14506 json_reverse_iterator operator+(difference_type i) const
14507 {
14508 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14509 }
14510
14512 json_reverse_iterator operator-(difference_type i) const
14513 {
14514 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14515 }
14516
14518 difference_type operator-(const json_reverse_iterator& other) const
14519 {
14520 return base_iterator(*this) - base_iterator(other);
14521 }
14522
14524 reference operator[](difference_type n) const
14525 {
14526 return *(this->operator+(n));
14527 }
14528
14530 auto key() const -> decltype(std::declval<Base>().key())
14531 {
14532 auto it = --this->base();
14533 return it.key();
14534 }
14535
14538 {
14539 auto it = --this->base();
14540 return it.operator * ();
14541 }
14542};
14543
14544} // namespace detail
14545NLOHMANN_JSON_NAMESPACE_END
14546
14547// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14548
14549// #include <nlohmann/detail/json_custom_base_class.hpp>
14550// __ _____ _____ _____
14551// __| | __| | | | JSON for Modern C++
14552// | | |__ | | | | | | version 3.12.0
14553// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14554//
14555// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
14556// SPDX-License-Identifier: MIT
14557
14558
14559
14560#include <type_traits> // conditional, is_same
14561
14562// #include <nlohmann/detail/abi_macros.hpp>
14563
14564
14565NLOHMANN_JSON_NAMESPACE_BEGIN
14566namespace detail
14567{
14568
14580
14581template<class T>
14582using json_base_class = typename std::conditional <
14583 std::is_same<T, void>::value,
14585 T
14586 >::type;
14587
14588} // namespace detail
14589NLOHMANN_JSON_NAMESPACE_END
14590
14591// #include <nlohmann/detail/json_pointer.hpp>
14592// __ _____ _____ _____
14593// __| | __| | | | JSON for Modern C++
14594// | | |__ | | | | | | version 3.12.0
14595// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14596//
14597// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
14598// SPDX-License-Identifier: MIT
14599
14600
14601
14602#include <algorithm> // all_of
14603#include <cctype> // isdigit
14604#include <cerrno> // errno, ERANGE
14605#include <cstdlib> // strtoull
14606#ifndef JSON_NO_IO
14607 #include <iosfwd> // ostream
14608#endif // JSON_NO_IO
14609#include <limits> // max
14610#include <numeric> // accumulate
14611#include <string> // string
14612#include <utility> // move
14613#include <vector> // vector
14614
14615// #include <nlohmann/detail/exceptions.hpp>
14616
14617// #include <nlohmann/detail/macro_scope.hpp>
14618
14619// #include <nlohmann/detail/string_concat.hpp>
14620
14621// #include <nlohmann/detail/string_escape.hpp>
14622
14623// #include <nlohmann/detail/value_t.hpp>
14624
14625
14626NLOHMANN_JSON_NAMESPACE_BEGIN
14627
14630template<typename RefStringType>
14631class json_pointer
14632{
14633 // allow basic_json to access private members
14634 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14635 friend class basic_json;
14636
14637 template<typename>
14638 friend class json_pointer;
14639
14640 template<typename T>
14641 struct string_t_helper
14642 {
14643 using type = T;
14644 };
14645
14646 NLOHMANN_BASIC_JSON_TPL_DECLARATION
14647 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14648 {
14649 using type = StringType;
14650 };
14651
14652 public:
14653 // for backwards compatibility accept BasicJsonType
14654 using string_t = typename string_t_helper<RefStringType>::type;
14655
14658 explicit json_pointer(const string_t& s = "")
14659 : reference_tokens(split(s))
14660 {}
14661
14664 string_t to_string() const
14665 {
14666 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14667 string_t{},
14668 [](const string_t& a, const string_t& b)
14669 {
14670 return detail::concat(a, '/', detail::escape(b));
14671 });
14672 }
14673
14676 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
14677 operator string_t() const
14678 {
14679 return to_string();
14680 }
14681
14682#ifndef JSON_NO_IO
14685 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14686 {
14687 o << ptr.to_string();
14688 return o;
14689 }
14690#endif
14691
14694 json_pointer& operator/=(const json_pointer& ptr)
14695 {
14696 reference_tokens.insert(reference_tokens.end(),
14697 ptr.reference_tokens.begin(),
14698 ptr.reference_tokens.end());
14699 return *this;
14700 }
14701
14704 json_pointer& operator/=(string_t token)
14705 {
14706 push_back(std::move(token));
14707 return *this;
14708 }
14709
14712 json_pointer& operator/=(std::size_t array_idx)
14713 {
14714 return *this /= std::to_string(array_idx);
14715 }
14716
14719 friend json_pointer operator/(const json_pointer& lhs,
14720 const json_pointer& rhs)
14721 {
14722 return json_pointer(lhs) /= rhs;
14723 }
14724
14727 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14728 {
14729 return json_pointer(lhs) /= std::move(token);
14730 }
14731
14734 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14735 {
14736 return json_pointer(lhs) /= array_idx;
14737 }
14738
14741 json_pointer parent_pointer() const
14742 {
14743 if (empty())
14744 {
14745 return *this;
14746 }
14747
14748 json_pointer res = *this;
14749 res.pop_back();
14750 return res;
14751 }
14752
14756 {
14757 if (JSON_HEDLEY_UNLIKELY(empty()))
14758 {
14759 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14760 }
14761
14762 reference_tokens.pop_back();
14763 }
14764
14767 const string_t& back() const
14768 {
14769 if (JSON_HEDLEY_UNLIKELY(empty()))
14770 {
14771 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14772 }
14773
14774 return reference_tokens.back();
14775 }
14776
14779 void push_back(const string_t& token)
14780 {
14781 reference_tokens.push_back(token);
14782 }
14783
14786 void push_back(string_t&& token)
14787 {
14788 reference_tokens.push_back(std::move(token));
14789 }
14790
14793 bool empty() const noexcept
14794 {
14795 return reference_tokens.empty();
14796 }
14797
14798 private:
14809 template<typename BasicJsonType>
14810 static typename BasicJsonType::size_type array_index(const string_t& s)
14811 {
14812 using size_type = typename BasicJsonType::size_type;
14813
14814 // error condition (cf. RFC 6901, Sect. 4)
14815 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14816 {
14817 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14818 }
14819
14820 // error condition (cf. RFC 6901, Sect. 4)
14821 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14822 {
14823 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14824 }
14825
14826 const char* p = s.c_str();
14827 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14828 errno = 0; // strtoull doesn't reset errno
14829 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14830 if (p == p_end // invalid input or empty string
14831 || errno == ERANGE // out of range
14832 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14833 {
14834 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14835 }
14836
14837 // only triggered on special platforms (like 32bit), see also
14838 // https://github.com/nlohmann/json/pull/2203
14839 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14840 {
14841 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14842 }
14843
14844 return static_cast<size_type>(res);
14845 }
14846
14847 JSON_PRIVATE_UNLESS_TESTED:
14848 json_pointer top() const
14849 {
14850 if (JSON_HEDLEY_UNLIKELY(empty()))
14851 {
14852 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14853 }
14854
14855 json_pointer result = *this;
14856 result.reference_tokens = {reference_tokens[0]};
14857 return result;
14858 }
14859
14860 private:
14869 template<typename BasicJsonType>
14870 BasicJsonType& get_and_create(BasicJsonType& j) const
14871 {
14872 auto* result = &j;
14873
14874 // in case no reference tokens exist, return a reference to the JSON value
14875 // j which will be overwritten by a primitive value
14876 for (const auto& reference_token : reference_tokens)
14877 {
14878 switch (result->type())
14879 {
14881 {
14882 if (reference_token == "0")
14883 {
14884 // start a new array if the reference token is 0
14885 result = &result->operator[](0);
14886 }
14887 else
14888 {
14889 // start a new object otherwise
14890 result = &result->operator[](reference_token);
14891 }
14892 break;
14893 }
14894
14896 {
14897 // create an entry in the object
14898 result = &result->operator[](reference_token);
14899 break;
14900 }
14901
14903 {
14904 // create an entry in the array
14905 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14906 break;
14907 }
14908
14909 /*
14910 The following code is only reached if there exists a reference
14911 token _and_ the current value is primitive. In this case, we have
14912 an error situation, because primitive values may only occur as
14913 a single value; that is, with an empty list of reference tokens.
14914 */
14922 default:
14923 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14924 }
14925 }
14926
14927 return *result;
14928 }
14929
14949 template<typename BasicJsonType>
14950 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14951 {
14952 for (const auto& reference_token : reference_tokens)
14953 {
14954 // convert null values to arrays or objects before continuing
14955 if (ptr->is_null())
14956 {
14957 // check if the reference token is a number
14958 const bool nums =
14959 std::all_of(reference_token.begin(), reference_token.end(),
14960 [](const unsigned char x)
14961 {
14962 return std::isdigit(x);
14963 });
14964
14965 // change value to an array for numbers or "-" or to object otherwise
14966 *ptr = (nums || reference_token == "-")
14968 : detail::value_t::object;
14969 }
14970
14971 switch (ptr->type())
14972 {
14974 {
14975 // use unchecked object access
14976 ptr = &ptr->operator[](reference_token);
14977 break;
14978 }
14979
14981 {
14982 if (reference_token == "-")
14983 {
14984 // explicitly treat "-" as index beyond the end
14985 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14986 }
14987 else
14988 {
14989 // convert array index to number; unchecked access
14990 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14991 }
14992 break;
14993 }
14994
15003 default:
15004 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15005 }
15006 }
15007
15008 return *ptr;
15009 }
15010
15017 template<typename BasicJsonType>
15018 BasicJsonType& get_checked(BasicJsonType* ptr) const
15019 {
15020 for (const auto& reference_token : reference_tokens)
15021 {
15022 switch (ptr->type())
15023 {
15025 {
15026 // note: at performs range check
15027 ptr = &ptr->at(reference_token);
15028 break;
15029 }
15030
15032 {
15033 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15034 {
15035 // "-" always fails the range check
15036 JSON_THROW(detail::out_of_range::create(402, detail::concat(
15037 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15038 ") is out of range"), ptr));
15039 }
15040
15041 // note: at performs range check
15042 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15043 break;
15044 }
15045
15054 default:
15055 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15056 }
15057 }
15058
15059 return *ptr;
15060 }
15061
15075 template<typename BasicJsonType>
15076 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15077 {
15078 for (const auto& reference_token : reference_tokens)
15079 {
15080 switch (ptr->type())
15081 {
15083 {
15084 // use unchecked object access
15085 ptr = &ptr->operator[](reference_token);
15086 break;
15087 }
15088
15090 {
15091 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15092 {
15093 // "-" cannot be used for const access
15094 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));
15095 }
15096
15097 // use unchecked array access
15098 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15099 break;
15100 }
15101
15110 default:
15111 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15112 }
15113 }
15114
15115 return *ptr;
15116 }
15117
15124 template<typename BasicJsonType>
15125 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15126 {
15127 for (const auto& reference_token : reference_tokens)
15128 {
15129 switch (ptr->type())
15130 {
15132 {
15133 // note: at performs range check
15134 ptr = &ptr->at(reference_token);
15135 break;
15136 }
15137
15139 {
15140 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15141 {
15142 // "-" always fails the range check
15143 JSON_THROW(detail::out_of_range::create(402, detail::concat(
15144 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15145 ") is out of range"), ptr));
15146 }
15147
15148 // note: at performs range check
15149 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15150 break;
15151 }
15152
15161 default:
15162 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15163 }
15164 }
15165
15166 return *ptr;
15167 }
15168
15173 template<typename BasicJsonType>
15174 bool contains(const BasicJsonType* ptr) const
15175 {
15176 for (const auto& reference_token : reference_tokens)
15177 {
15178 switch (ptr->type())
15179 {
15181 {
15182 if (!ptr->contains(reference_token))
15183 {
15184 // we did not find the key in the object
15185 return false;
15186 }
15187
15188 ptr = &ptr->operator[](reference_token);
15189 break;
15190 }
15191
15193 {
15194 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15195 {
15196 // "-" always fails the range check
15197 return false;
15198 }
15199 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15200 {
15201 // invalid char
15202 return false;
15203 }
15204 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15205 {
15206 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15207 {
15208 // the first char should be between '1' and '9'
15209 return false;
15210 }
15211 for (std::size_t i = 1; i < reference_token.size(); i++)
15212 {
15213 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15214 {
15215 // other char should be between '0' and '9'
15216 return false;
15217 }
15218 }
15219 }
15220
15221 const auto idx = array_index<BasicJsonType>(reference_token);
15222 if (idx >= ptr->size())
15223 {
15224 // index out of range
15225 return false;
15226 }
15227
15228 ptr = &ptr->operator[](idx);
15229 break;
15230 }
15231
15240 default:
15241 {
15242 // we do not expect primitive values if there is still a
15243 // reference token to process
15244 return false;
15245 }
15246 }
15247 }
15248
15249 // no reference token left means we found a primitive value
15250 return true;
15251 }
15252
15262 static std::vector<string_t> split(const string_t& reference_string)
15263 {
15264 std::vector<string_t> result;
15265
15266 // special case: empty reference string -> no reference tokens
15267 if (reference_string.empty())
15268 {
15269 return result;
15270 }
15271
15272 // check if a nonempty reference string begins with slash
15273 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15274 {
15275 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15276 }
15277
15278 // extract the reference tokens:
15279 // - slash: position of the last read slash (or end of string)
15280 // - start: position after the previous slash
15281 for (
15282 // search for the first slash after the first character
15283 std::size_t slash = reference_string.find_first_of('/', 1),
15284 // set the beginning of the first reference token
15285 start = 1;
15286 // we can stop if start == 0 (if slash == string_t::npos)
15287 start != 0;
15288 // set the beginning of the next reference token
15289 // (will eventually be 0 if slash == string_t::npos)
15290 start = (slash == string_t::npos) ? 0 : slash + 1,
15291 // find next slash
15292 slash = reference_string.find_first_of('/', start))
15293 {
15294 // use the text between the beginning of the reference token
15295 // (start) and the last slash (slash).
15296 auto reference_token = reference_string.substr(start, slash - start);
15297
15298 // check reference tokens are properly escaped
15299 for (std::size_t pos = reference_token.find_first_of('~');
15300 pos != string_t::npos;
15301 pos = reference_token.find_first_of('~', pos + 1))
15302 {
15303 JSON_ASSERT(reference_token[pos] == '~');
15304
15305 // ~ must be followed by 0 or 1
15306 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15307 (reference_token[pos + 1] != '0' &&
15308 reference_token[pos + 1] != '1')))
15309 {
15310 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15311 }
15312 }
15313
15314 // finally, store the reference token
15315 detail::unescape(reference_token);
15316 result.push_back(reference_token);
15317 }
15318
15319 return result;
15320 }
15321
15322 private:
15330 template<typename BasicJsonType>
15331 static void flatten(const string_t& reference_string,
15332 const BasicJsonType& value,
15333 BasicJsonType& result)
15334 {
15335 switch (value.type())
15336 {
15338 {
15339 if (value.m_data.m_value.array->empty())
15340 {
15341 // flatten empty array as null
15342 result[reference_string] = nullptr;
15343 }
15344 else
15345 {
15346 // iterate array and use index as a reference string
15347 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15348 {
15349 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15350 value.m_data.m_value.array->operator[](i), result);
15351 }
15352 }
15353 break;
15354 }
15355
15357 {
15358 if (value.m_data.m_value.object->empty())
15359 {
15360 // flatten empty object as null
15361 result[reference_string] = nullptr;
15362 }
15363 else
15364 {
15365 // iterate object and use keys as reference string
15366 for (const auto& element : *value.m_data.m_value.object)
15367 {
15368 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15369 }
15370 }
15371 break;
15372 }
15373
15382 default:
15383 {
15384 // add a primitive value with its reference string
15385 result[reference_string] = value;
15386 break;
15387 }
15388 }
15389 }
15390
15401 template<typename BasicJsonType>
15402 static BasicJsonType
15403 unflatten(const BasicJsonType& value)
15404 {
15405 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15406 {
15407 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15408 }
15409
15410 BasicJsonType result;
15411
15412 // iterate the JSON object values
15413 for (const auto& element : *value.m_data.m_value.object)
15414 {
15415 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15416 {
15417 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15418 }
15419
15420 // Assign the value to the reference pointed to by JSON pointer. Note
15421 // that if the JSON pointer is "" (i.e., points to the whole value),
15422 // function get_and_create returns a reference to the result itself.
15423 // An assignment will then create a primitive value.
15424 json_pointer(element.first).get_and_create(result) = element.second;
15425 }
15426
15427 return result;
15428 }
15429
15430 // can't use the conversion operator because of ambiguity
15431 json_pointer<string_t> convert() const&
15432 {
15433 json_pointer<string_t> result;
15434 result.reference_tokens = reference_tokens;
15435 return result;
15436 }
15437
15438 json_pointer<string_t> convert()&&
15439 {
15440 json_pointer<string_t> result;
15441 result.reference_tokens = std::move(reference_tokens);
15442 return result;
15443 }
15444
15445 public:
15446#if JSON_HAS_THREE_WAY_COMPARISON
15449 template<typename RefStringTypeRhs>
15450 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15451 {
15452 return reference_tokens == rhs.reference_tokens;
15453 }
15454
15457 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15458 bool operator==(const string_t& rhs) const
15459 {
15460 return *this == json_pointer(rhs);
15461 }
15462
15464 template<typename RefStringTypeRhs>
15465 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15466 {
15467 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15468 }
15469#else
15472 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15473 // NOLINTNEXTLINE(readability-redundant-declaration)
15474 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15475 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15476
15479 template<typename RefStringTypeLhs, typename StringType>
15480 // NOLINTNEXTLINE(readability-redundant-declaration)
15481 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15482 const StringType& rhs);
15483
15486 template<typename RefStringTypeRhs, typename StringType>
15487 // NOLINTNEXTLINE(readability-redundant-declaration)
15488 friend bool operator==(const StringType& lhs,
15489 const json_pointer<RefStringTypeRhs>& rhs);
15490
15493 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15494 // NOLINTNEXTLINE(readability-redundant-declaration)
15495 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15496 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15497
15500 template<typename RefStringTypeLhs, typename StringType>
15501 // NOLINTNEXTLINE(readability-redundant-declaration)
15502 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15503 const StringType& rhs);
15504
15507 template<typename RefStringTypeRhs, typename StringType>
15508 // NOLINTNEXTLINE(readability-redundant-declaration)
15509 friend bool operator!=(const StringType& lhs,
15510 const json_pointer<RefStringTypeRhs>& rhs);
15511
15513 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15514 // NOLINTNEXTLINE(readability-redundant-declaration)
15515 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15516 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15517#endif
15518
15519 private:
15521 std::vector<string_t> reference_tokens;
15522};
15523
15524#if !JSON_HAS_THREE_WAY_COMPARISON
15525// functions cannot be defined inside the class due to ODR violations
15526template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15527inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15528 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15529{
15530 return lhs.reference_tokens == rhs.reference_tokens;
15531}
15532
15533template<typename RefStringTypeLhs,
15534 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15535JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15536inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15537 const StringType& rhs)
15538{
15539 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15540}
15541
15542template<typename RefStringTypeRhs,
15543 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15544JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15545inline bool operator==(const StringType& lhs,
15546 const json_pointer<RefStringTypeRhs>& rhs)
15547{
15548 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15549}
15550
15551template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15552inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15553 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15554{
15555 return !(lhs == rhs);
15556}
15557
15558template<typename RefStringTypeLhs,
15559 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15560JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15561inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15562 const StringType& rhs)
15563{
15564 return !(lhs == rhs);
15565}
15566
15567template<typename RefStringTypeRhs,
15568 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15569JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15570inline bool operator!=(const StringType& lhs,
15571 const json_pointer<RefStringTypeRhs>& rhs)
15572{
15573 return !(lhs == rhs);
15574}
15575
15576template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15577inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15578 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15579{
15580 return lhs.reference_tokens < rhs.reference_tokens;
15581}
15582#endif
15583
15584NLOHMANN_JSON_NAMESPACE_END
15585
15586// #include <nlohmann/detail/json_ref.hpp>
15587// __ _____ _____ _____
15588// __| | __| | | | JSON for Modern C++
15589// | | |__ | | | | | | version 3.12.0
15590// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15591//
15592// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
15593// SPDX-License-Identifier: MIT
15594
15595
15596
15597#include <initializer_list>
15598#include <utility>
15599
15600// #include <nlohmann/detail/abi_macros.hpp>
15601
15602// #include <nlohmann/detail/meta/type_traits.hpp>
15603
15604
15605NLOHMANN_JSON_NAMESPACE_BEGIN
15606namespace detail
15607{
15608
15609template<typename BasicJsonType>
15610class json_ref
15611{
15612 public:
15613 using value_type = BasicJsonType;
15614
15615 json_ref(value_type&& value)
15616 : owned_value(std::move(value))
15617 {}
15618
15619 json_ref(const value_type& value)
15620 : value_ref(&value)
15621 {}
15622
15623 json_ref(std::initializer_list<json_ref> init)
15624 : owned_value(init)
15625 {}
15626
15627 template <
15628 class... Args,
15629 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15630 json_ref(Args && ... args)
15631 : owned_value(std::forward<Args>(args)...)
15632 {}
15633
15634 // class should be movable only
15635 json_ref(json_ref&&) noexcept = default;
15636 json_ref(const json_ref&) = delete;
15637 json_ref& operator=(const json_ref&) = delete;
15638 json_ref& operator=(json_ref&&) = delete;
15639 ~json_ref() = default;
15640
15641 value_type moved_or_copied() const
15642 {
15643 if (value_ref == nullptr)
15644 {
15645 return std::move(owned_value);
15646 }
15647 return *value_ref;
15648 }
15649
15650 value_type const& operator*() const
15651 {
15652 return value_ref ? *value_ref : owned_value;
15653 }
15654
15655 value_type const* operator->() const
15656 {
15657 return &** this;
15658 }
15659
15660 private:
15661 mutable value_type owned_value = nullptr;
15662 value_type const* value_ref = nullptr;
15663};
15664
15665} // namespace detail
15666NLOHMANN_JSON_NAMESPACE_END
15667
15668// #include <nlohmann/detail/macro_scope.hpp>
15669
15670// #include <nlohmann/detail/string_concat.hpp>
15671
15672// #include <nlohmann/detail/string_escape.hpp>
15673
15674// #include <nlohmann/detail/string_utils.hpp>
15675
15676// #include <nlohmann/detail/meta/cpp_future.hpp>
15677
15678// #include <nlohmann/detail/meta/type_traits.hpp>
15679
15680// #include <nlohmann/detail/output/binary_writer.hpp>
15681// __ _____ _____ _____
15682// __| | __| | | | JSON for Modern C++
15683// | | |__ | | | | | | version 3.12.0
15684// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15685//
15686// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
15687// SPDX-License-Identifier: MIT
15688
15689
15690
15691#include <algorithm> // reverse
15692#include <array> // array
15693#include <map> // map
15694#include <cmath> // isnan, isinf
15695#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15696#include <cstring> // memcpy
15697#include <limits> // numeric_limits
15698#include <string> // string
15699#include <utility> // move
15700#include <vector> // vector
15701
15702// #include <nlohmann/detail/input/binary_reader.hpp>
15703
15704// #include <nlohmann/detail/macro_scope.hpp>
15705
15706// #include <nlohmann/detail/output/output_adapters.hpp>
15707// __ _____ _____ _____
15708// __| | __| | | | JSON for Modern C++
15709// | | |__ | | | | | | version 3.12.0
15710// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15711//
15712// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
15713// SPDX-License-Identifier: MIT
15714
15715
15716
15717#include <algorithm> // copy
15718#include <cstddef> // size_t
15719#include <iterator> // back_inserter
15720#include <memory> // shared_ptr, make_shared
15721#include <string> // basic_string
15722#include <vector> // vector
15723
15724#ifndef JSON_NO_IO
15725 #include <ios> // streamsize
15726 #include <ostream> // basic_ostream
15727#endif // JSON_NO_IO
15728
15729// #include <nlohmann/detail/macro_scope.hpp>
15730
15731
15732NLOHMANN_JSON_NAMESPACE_BEGIN
15733namespace detail
15734{
15735
15737template<typename CharType> struct output_adapter_protocol
15738{
15739 virtual void write_character(CharType c) = 0;
15740 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15741 virtual ~output_adapter_protocol() = default;
15742
15743 output_adapter_protocol() = default;
15744 output_adapter_protocol(const output_adapter_protocol&) = default;
15745 output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15746 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15747 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15748};
15749
15751template<typename CharType>
15752using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15753
15755template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15756class output_vector_adapter : public output_adapter_protocol<CharType>
15757{
15758 public:
15759 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15760 : v(vec)
15761 {}
15762
15763 void write_character(CharType c) override
15764 {
15765 v.push_back(c);
15766 }
15767
15768 JSON_HEDLEY_NON_NULL(2)
15769 void write_characters(const CharType* s, std::size_t length) override
15770 {
15771 v.insert(v.end(), s, s + length);
15772 }
15773
15774 private:
15775 std::vector<CharType, AllocatorType>& v;
15776};
15777
15778#ifndef JSON_NO_IO
15780template<typename CharType>
15781class output_stream_adapter : public output_adapter_protocol<CharType>
15782{
15783 public:
15784 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15785 : stream(s)
15786 {}
15787
15788 void write_character(CharType c) override
15789 {
15790 stream.put(c);
15791 }
15792
15793 JSON_HEDLEY_NON_NULL(2)
15794 void write_characters(const CharType* s, std::size_t length) override
15795 {
15796 stream.write(s, static_cast<std::streamsize>(length));
15797 }
15798
15799 private:
15800 std::basic_ostream<CharType>& stream;
15801};
15802#endif // JSON_NO_IO
15803
15805template<typename CharType, typename StringType = std::basic_string<CharType>>
15806class output_string_adapter : public output_adapter_protocol<CharType>
15807{
15808 public:
15809 explicit output_string_adapter(StringType& s) noexcept
15810 : str(s)
15811 {}
15812
15813 void write_character(CharType c) override
15814 {
15815 str.push_back(c);
15816 }
15817
15818 JSON_HEDLEY_NON_NULL(2)
15819 void write_characters(const CharType* s, std::size_t length) override
15820 {
15821 str.append(s, length);
15822 }
15823
15824 private:
15825 StringType& str;
15826};
15827
15828template<typename CharType, typename StringType = std::basic_string<CharType>>
15829class output_adapter
15830{
15831 public:
15832 template<typename AllocatorType = std::allocator<CharType>>
15833 output_adapter(std::vector<CharType, AllocatorType>& vec)
15834 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15835
15836#ifndef JSON_NO_IO
15837 output_adapter(std::basic_ostream<CharType>& s)
15838 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15839#endif // JSON_NO_IO
15840
15841 output_adapter(StringType& s)
15842 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15843
15845 {
15846 return oa;
15847 }
15848
15849 private:
15850 output_adapter_t<CharType> oa = nullptr;
15851};
15852
15853} // namespace detail
15854NLOHMANN_JSON_NAMESPACE_END
15855
15856// #include <nlohmann/detail/string_concat.hpp>
15857
15858
15859NLOHMANN_JSON_NAMESPACE_BEGIN
15860namespace detail
15861{
15862
15865{
15866 draft2,
15867 draft3,
15868};
15869
15871// binary writer //
15873
15877template<typename BasicJsonType, typename CharType>
15879{
15880 using string_t = typename BasicJsonType::string_t;
15881 using binary_t = typename BasicJsonType::binary_t;
15882 using number_float_t = typename BasicJsonType::number_float_t;
15883
15884 public:
15890 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15891 {
15892 JSON_ASSERT(oa);
15893 }
15894
15899 void write_bson(const BasicJsonType& j)
15900 {
15901 switch (j.type())
15902 {
15903 case value_t::object:
15904 {
15905 write_bson_object(*j.m_data.m_value.object);
15906 break;
15907 }
15908
15909 case value_t::null:
15910 case value_t::array:
15911 case value_t::string:
15912 case value_t::boolean:
15916 case value_t::binary:
15917 case value_t::discarded:
15918 default:
15919 {
15920 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15921 }
15922 }
15923 }
15924
15928 void write_cbor(const BasicJsonType& j)
15929 {
15930 switch (j.type())
15931 {
15932 case value_t::null:
15933 {
15934 oa->write_character(to_char_type(0xF6));
15935 break;
15936 }
15937
15938 case value_t::boolean:
15939 {
15940 oa->write_character(j.m_data.m_value.boolean
15941 ? to_char_type(0xF5)
15942 : to_char_type(0xF4));
15943 break;
15944 }
15945
15947 {
15948 if (j.m_data.m_value.number_integer >= 0)
15949 {
15950 // CBOR does not differentiate between positive signed
15951 // integers and unsigned integers. Therefore, we used the
15952 // code from the value_t::number_unsigned case here.
15953 if (j.m_data.m_value.number_integer <= 0x17)
15954 {
15955 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15956 }
15957 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15958 {
15959 oa->write_character(to_char_type(0x18));
15960 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15961 }
15962 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15963 {
15964 oa->write_character(to_char_type(0x19));
15965 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15966 }
15967 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15968 {
15969 oa->write_character(to_char_type(0x1A));
15970 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15971 }
15972 else
15973 {
15974 oa->write_character(to_char_type(0x1B));
15975 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15976 }
15977 }
15978 else
15979 {
15980 // The conversions below encode the sign in the first
15981 // byte, and the value is converted to a positive number.
15982 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15983 if (j.m_data.m_value.number_integer >= -24)
15984 {
15985 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15986 }
15987 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15988 {
15989 oa->write_character(to_char_type(0x38));
15990 write_number(static_cast<std::uint8_t>(positive_number));
15991 }
15992 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15993 {
15994 oa->write_character(to_char_type(0x39));
15995 write_number(static_cast<std::uint16_t>(positive_number));
15996 }
15997 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15998 {
15999 oa->write_character(to_char_type(0x3A));
16000 write_number(static_cast<std::uint32_t>(positive_number));
16001 }
16002 else
16003 {
16004 oa->write_character(to_char_type(0x3B));
16005 write_number(static_cast<std::uint64_t>(positive_number));
16006 }
16007 }
16008 break;
16009 }
16010
16012 {
16013 if (j.m_data.m_value.number_unsigned <= 0x17)
16014 {
16015 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16016 }
16017 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16018 {
16019 oa->write_character(to_char_type(0x18));
16020 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
16021 }
16022 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16023 {
16024 oa->write_character(to_char_type(0x19));
16025 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
16026 }
16027 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16028 {
16029 oa->write_character(to_char_type(0x1A));
16030 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
16031 }
16032 else
16033 {
16034 oa->write_character(to_char_type(0x1B));
16035 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
16036 }
16037 break;
16038 }
16039
16041 {
16042 if (std::isnan(j.m_data.m_value.number_float))
16043 {
16044 // NaN is 0xf97e00 in CBOR
16045 oa->write_character(to_char_type(0xF9));
16046 oa->write_character(to_char_type(0x7E));
16047 oa->write_character(to_char_type(0x00));
16048 }
16049 else if (std::isinf(j.m_data.m_value.number_float))
16050 {
16051 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16052 oa->write_character(to_char_type(0xf9));
16053 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16054 oa->write_character(to_char_type(0x00));
16055 }
16056 else
16057 {
16058 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16059 }
16060 break;
16061 }
16062
16063 case value_t::string:
16064 {
16065 // step 1: write control byte and the string length
16066 const auto N = j.m_data.m_value.string->size();
16067 if (N <= 0x17)
16068 {
16069 write_number(static_cast<std::uint8_t>(0x60 + N));
16070 }
16071 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16072 {
16073 oa->write_character(to_char_type(0x78));
16074 write_number(static_cast<std::uint8_t>(N));
16075 }
16076 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16077 {
16078 oa->write_character(to_char_type(0x79));
16079 write_number(static_cast<std::uint16_t>(N));
16080 }
16081 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16082 {
16083 oa->write_character(to_char_type(0x7A));
16084 write_number(static_cast<std::uint32_t>(N));
16085 }
16086 // LCOV_EXCL_START
16087 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16088 {
16089 oa->write_character(to_char_type(0x7B));
16090 write_number(static_cast<std::uint64_t>(N));
16091 }
16092 // LCOV_EXCL_STOP
16093
16094 // step 2: write the string
16095 oa->write_characters(
16096 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16097 j.m_data.m_value.string->size());
16098 break;
16099 }
16100
16101 case value_t::array:
16102 {
16103 // step 1: write control byte and the array size
16104 const auto N = j.m_data.m_value.array->size();
16105 if (N <= 0x17)
16106 {
16107 write_number(static_cast<std::uint8_t>(0x80 + N));
16108 }
16109 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16110 {
16111 oa->write_character(to_char_type(0x98));
16112 write_number(static_cast<std::uint8_t>(N));
16113 }
16114 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16115 {
16116 oa->write_character(to_char_type(0x99));
16117 write_number(static_cast<std::uint16_t>(N));
16118 }
16119 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16120 {
16121 oa->write_character(to_char_type(0x9A));
16122 write_number(static_cast<std::uint32_t>(N));
16123 }
16124 // LCOV_EXCL_START
16125 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16126 {
16127 oa->write_character(to_char_type(0x9B));
16128 write_number(static_cast<std::uint64_t>(N));
16129 }
16130 // LCOV_EXCL_STOP
16131
16132 // step 2: write each element
16133 for (const auto& el : *j.m_data.m_value.array)
16134 {
16135 write_cbor(el);
16136 }
16137 break;
16138 }
16139
16140 case value_t::binary:
16141 {
16142 if (j.m_data.m_value.binary->has_subtype())
16143 {
16144 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16145 {
16146 write_number(static_cast<std::uint8_t>(0xd8));
16147 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16148 }
16149 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16150 {
16151 write_number(static_cast<std::uint8_t>(0xd9));
16152 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16153 }
16154 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16155 {
16156 write_number(static_cast<std::uint8_t>(0xda));
16157 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16158 }
16159 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16160 {
16161 write_number(static_cast<std::uint8_t>(0xdb));
16162 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16163 }
16164 }
16165
16166 // step 1: write control byte and the binary array size
16167 const auto N = j.m_data.m_value.binary->size();
16168 if (N <= 0x17)
16169 {
16170 write_number(static_cast<std::uint8_t>(0x40 + N));
16171 }
16172 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16173 {
16174 oa->write_character(to_char_type(0x58));
16175 write_number(static_cast<std::uint8_t>(N));
16176 }
16177 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16178 {
16179 oa->write_character(to_char_type(0x59));
16180 write_number(static_cast<std::uint16_t>(N));
16181 }
16182 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16183 {
16184 oa->write_character(to_char_type(0x5A));
16185 write_number(static_cast<std::uint32_t>(N));
16186 }
16187 // LCOV_EXCL_START
16188 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16189 {
16190 oa->write_character(to_char_type(0x5B));
16191 write_number(static_cast<std::uint64_t>(N));
16192 }
16193 // LCOV_EXCL_STOP
16194
16195 // step 2: write each element
16196 oa->write_characters(
16197 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16198 N);
16199
16200 break;
16201 }
16202
16203 case value_t::object:
16204 {
16205 // step 1: write control byte and the object size
16206 const auto N = j.m_data.m_value.object->size();
16207 if (N <= 0x17)
16208 {
16209 write_number(static_cast<std::uint8_t>(0xA0 + N));
16210 }
16211 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16212 {
16213 oa->write_character(to_char_type(0xB8));
16214 write_number(static_cast<std::uint8_t>(N));
16215 }
16216 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16217 {
16218 oa->write_character(to_char_type(0xB9));
16219 write_number(static_cast<std::uint16_t>(N));
16220 }
16221 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16222 {
16223 oa->write_character(to_char_type(0xBA));
16224 write_number(static_cast<std::uint32_t>(N));
16225 }
16226 // LCOV_EXCL_START
16227 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16228 {
16229 oa->write_character(to_char_type(0xBB));
16230 write_number(static_cast<std::uint64_t>(N));
16231 }
16232 // LCOV_EXCL_STOP
16233
16234 // step 2: write each element
16235 for (const auto& el : *j.m_data.m_value.object)
16236 {
16237 write_cbor(el.first);
16238 write_cbor(el.second);
16239 }
16240 break;
16241 }
16242
16243 case value_t::discarded:
16244 default:
16245 break;
16246 }
16247 }
16248
16252 void write_msgpack(const BasicJsonType& j)
16253 {
16254 switch (j.type())
16255 {
16256 case value_t::null: // nil
16257 {
16258 oa->write_character(to_char_type(0xC0));
16259 break;
16260 }
16261
16262 case value_t::boolean: // true and false
16263 {
16264 oa->write_character(j.m_data.m_value.boolean
16265 ? to_char_type(0xC3)
16266 : to_char_type(0xC2));
16267 break;
16268 }
16269
16271 {
16272 if (j.m_data.m_value.number_integer >= 0)
16273 {
16274 // MessagePack does not differentiate between positive
16275 // signed integers and unsigned integers. Therefore, we used
16276 // the code from the value_t::number_unsigned case here.
16277 if (j.m_data.m_value.number_unsigned < 128)
16278 {
16279 // positive fixnum
16280 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16281 }
16282 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16283 {
16284 // uint 8
16285 oa->write_character(to_char_type(0xCC));
16286 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16287 }
16288 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16289 {
16290 // uint 16
16291 oa->write_character(to_char_type(0xCD));
16292 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16293 }
16294 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16295 {
16296 // uint 32
16297 oa->write_character(to_char_type(0xCE));
16298 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16299 }
16300 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16301 {
16302 // uint 64
16303 oa->write_character(to_char_type(0xCF));
16304 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16305 }
16306 }
16307 else
16308 {
16309 if (j.m_data.m_value.number_integer >= -32)
16310 {
16311 // negative fixnum
16312 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16313 }
16314 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16315 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16316 {
16317 // int 8
16318 oa->write_character(to_char_type(0xD0));
16319 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16320 }
16321 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16322 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16323 {
16324 // int 16
16325 oa->write_character(to_char_type(0xD1));
16326 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16327 }
16328 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16329 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16330 {
16331 // int 32
16332 oa->write_character(to_char_type(0xD2));
16333 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16334 }
16335 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16336 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16337 {
16338 // int 64
16339 oa->write_character(to_char_type(0xD3));
16340 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16341 }
16342 }
16343 break;
16344 }
16345
16347 {
16348 if (j.m_data.m_value.number_unsigned < 128)
16349 {
16350 // positive fixnum
16351 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16352 }
16353 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16354 {
16355 // uint 8
16356 oa->write_character(to_char_type(0xCC));
16357 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16358 }
16359 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16360 {
16361 // uint 16
16362 oa->write_character(to_char_type(0xCD));
16363 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16364 }
16365 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16366 {
16367 // uint 32
16368 oa->write_character(to_char_type(0xCE));
16369 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16370 }
16371 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16372 {
16373 // uint 64
16374 oa->write_character(to_char_type(0xCF));
16375 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16376 }
16377 break;
16378 }
16379
16381 {
16382 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16383 break;
16384 }
16385
16386 case value_t::string:
16387 {
16388 // step 1: write control byte and the string length
16389 const auto N = j.m_data.m_value.string->size();
16390 if (N <= 31)
16391 {
16392 // fixstr
16393 write_number(static_cast<std::uint8_t>(0xA0 | N));
16394 }
16395 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16396 {
16397 // str 8
16398 oa->write_character(to_char_type(0xD9));
16399 write_number(static_cast<std::uint8_t>(N));
16400 }
16401 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16402 {
16403 // str 16
16404 oa->write_character(to_char_type(0xDA));
16405 write_number(static_cast<std::uint16_t>(N));
16406 }
16407 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16408 {
16409 // str 32
16410 oa->write_character(to_char_type(0xDB));
16411 write_number(static_cast<std::uint32_t>(N));
16412 }
16413
16414 // step 2: write the string
16415 oa->write_characters(
16416 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16417 j.m_data.m_value.string->size());
16418 break;
16419 }
16420
16421 case value_t::array:
16422 {
16423 // step 1: write control byte and the array size
16424 const auto N = j.m_data.m_value.array->size();
16425 if (N <= 15)
16426 {
16427 // fixarray
16428 write_number(static_cast<std::uint8_t>(0x90 | N));
16429 }
16430 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16431 {
16432 // array 16
16433 oa->write_character(to_char_type(0xDC));
16434 write_number(static_cast<std::uint16_t>(N));
16435 }
16436 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16437 {
16438 // array 32
16439 oa->write_character(to_char_type(0xDD));
16440 write_number(static_cast<std::uint32_t>(N));
16441 }
16442
16443 // step 2: write each element
16444 for (const auto& el : *j.m_data.m_value.array)
16445 {
16446 write_msgpack(el);
16447 }
16448 break;
16449 }
16450
16451 case value_t::binary:
16452 {
16453 // step 0: determine if the binary type has a set subtype to
16454 // determine whether to use the ext or fixext types
16455 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16456
16457 // step 1: write control byte and the byte string length
16458 const auto N = j.m_data.m_value.binary->size();
16459 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16460 {
16461 std::uint8_t output_type{};
16462 bool fixed = true;
16463 if (use_ext)
16464 {
16465 switch (N)
16466 {
16467 case 1:
16468 output_type = 0xD4; // fixext 1
16469 break;
16470 case 2:
16471 output_type = 0xD5; // fixext 2
16472 break;
16473 case 4:
16474 output_type = 0xD6; // fixext 4
16475 break;
16476 case 8:
16477 output_type = 0xD7; // fixext 8
16478 break;
16479 case 16:
16480 output_type = 0xD8; // fixext 16
16481 break;
16482 default:
16483 output_type = 0xC7; // ext 8
16484 fixed = false;
16485 break;
16486 }
16487
16488 }
16489 else
16490 {
16491 output_type = 0xC4; // bin 8
16492 fixed = false;
16493 }
16494
16495 oa->write_character(to_char_type(output_type));
16496 if (!fixed)
16497 {
16498 write_number(static_cast<std::uint8_t>(N));
16499 }
16500 }
16501 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16502 {
16503 const std::uint8_t output_type = use_ext
16504 ? 0xC8 // ext 16
16505 : 0xC5; // bin 16
16506
16507 oa->write_character(to_char_type(output_type));
16508 write_number(static_cast<std::uint16_t>(N));
16509 }
16510 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16511 {
16512 const std::uint8_t output_type = use_ext
16513 ? 0xC9 // ext 32
16514 : 0xC6; // bin 32
16515
16516 oa->write_character(to_char_type(output_type));
16517 write_number(static_cast<std::uint32_t>(N));
16518 }
16519
16520 // step 1.5: if this is an ext type, write the subtype
16521 if (use_ext)
16522 {
16523 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16524 }
16525
16526 // step 2: write the byte string
16527 oa->write_characters(
16528 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16529 N);
16530
16531 break;
16532 }
16533
16534 case value_t::object:
16535 {
16536 // step 1: write control byte and the object size
16537 const auto N = j.m_data.m_value.object->size();
16538 if (N <= 15)
16539 {
16540 // fixmap
16541 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16542 }
16543 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16544 {
16545 // map 16
16546 oa->write_character(to_char_type(0xDE));
16547 write_number(static_cast<std::uint16_t>(N));
16548 }
16549 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16550 {
16551 // map 32
16552 oa->write_character(to_char_type(0xDF));
16553 write_number(static_cast<std::uint32_t>(N));
16554 }
16555
16556 // step 2: write each element
16557 for (const auto& el : *j.m_data.m_value.object)
16558 {
16559 write_msgpack(el.first);
16560 write_msgpack(el.second);
16561 }
16562 break;
16563 }
16564
16565 case value_t::discarded:
16566 default:
16567 break;
16568 }
16569 }
16570
16579 void write_ubjson(const BasicJsonType& j, const bool use_count,
16580 const bool use_type, const bool add_prefix = true,
16581 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16582 {
16583 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16584
16585 switch (j.type())
16586 {
16587 case value_t::null:
16588 {
16589 if (add_prefix)
16590 {
16591 oa->write_character(to_char_type('Z'));
16592 }
16593 break;
16594 }
16595
16596 case value_t::boolean:
16597 {
16598 if (add_prefix)
16599 {
16600 oa->write_character(j.m_data.m_value.boolean
16601 ? to_char_type('T')
16602 : to_char_type('F'));
16603 }
16604 break;
16605 }
16606
16608 {
16609 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16610 break;
16611 }
16612
16614 {
16615 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16616 break;
16617 }
16618
16620 {
16621 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16622 break;
16623 }
16624
16625 case value_t::string:
16626 {
16627 if (add_prefix)
16628 {
16629 oa->write_character(to_char_type('S'));
16630 }
16631 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16632 oa->write_characters(
16633 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16634 j.m_data.m_value.string->size());
16635 break;
16636 }
16637
16638 case value_t::array:
16639 {
16640 if (add_prefix)
16641 {
16642 oa->write_character(to_char_type('['));
16643 }
16644
16645 bool prefix_required = true;
16646 if (use_type && !j.m_data.m_value.array->empty())
16647 {
16648 JSON_ASSERT(use_count);
16649 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16650 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16651 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16652 {
16653 return ubjson_prefix(v, use_bjdata) == first_prefix;
16654 });
16655
16656 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16657
16658 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16659 {
16660 prefix_required = false;
16661 oa->write_character(to_char_type('$'));
16662 oa->write_character(first_prefix);
16663 }
16664 }
16665
16666 if (use_count)
16667 {
16668 oa->write_character(to_char_type('#'));
16669 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16670 }
16671
16672 for (const auto& el : *j.m_data.m_value.array)
16673 {
16674 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16675 }
16676
16677 if (!use_count)
16678 {
16679 oa->write_character(to_char_type(']'));
16680 }
16681
16682 break;
16683 }
16684
16685 case value_t::binary:
16686 {
16687 if (add_prefix)
16688 {
16689 oa->write_character(to_char_type('['));
16690 }
16691
16692 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16693 {
16694 JSON_ASSERT(use_count);
16695 oa->write_character(to_char_type('$'));
16696 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16697 }
16698
16699 if (use_count)
16700 {
16701 oa->write_character(to_char_type('#'));
16702 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16703 }
16704
16705 if (use_type)
16706 {
16707 oa->write_characters(
16708 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16709 j.m_data.m_value.binary->size());
16710 }
16711 else
16712 {
16713 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16714 {
16715 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16716 oa->write_character(j.m_data.m_value.binary->data()[i]);
16717 }
16718 }
16719
16720 if (!use_count)
16721 {
16722 oa->write_character(to_char_type(']'));
16723 }
16724
16725 break;
16726 }
16727
16728 case value_t::object:
16729 {
16730 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())
16731 {
16732 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)
16733 {
16734 break;
16735 }
16736 }
16737
16738 if (add_prefix)
16739 {
16740 oa->write_character(to_char_type('{'));
16741 }
16742
16743 bool prefix_required = true;
16744 if (use_type && !j.m_data.m_value.object->empty())
16745 {
16746 JSON_ASSERT(use_count);
16747 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16748 const bool same_prefix = std::all_of(j.begin(), j.end(),
16749 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16750 {
16751 return ubjson_prefix(v, use_bjdata) == first_prefix;
16752 });
16753
16754 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16755
16756 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16757 {
16758 prefix_required = false;
16759 oa->write_character(to_char_type('$'));
16760 oa->write_character(first_prefix);
16761 }
16762 }
16763
16764 if (use_count)
16765 {
16766 oa->write_character(to_char_type('#'));
16767 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16768 }
16769
16770 for (const auto& el : *j.m_data.m_value.object)
16771 {
16772 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16773 oa->write_characters(
16774 reinterpret_cast<const CharType*>(el.first.c_str()),
16775 el.first.size());
16776 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16777 }
16778
16779 if (!use_count)
16780 {
16781 oa->write_character(to_char_type('}'));
16782 }
16783
16784 break;
16785 }
16786
16787 case value_t::discarded:
16788 default:
16789 break;
16790 }
16791 }
16792
16793 private:
16795 // BSON //
16797
16802 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16803 {
16804 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16805 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16806 {
16807 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16808 }
16809
16810 static_cast<void>(j);
16811 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16812 }
16813
16817 void write_bson_entry_header(const string_t& name,
16818 const std::uint8_t element_type)
16819 {
16820 oa->write_character(to_char_type(element_type)); // boolean
16821 oa->write_characters(
16822 reinterpret_cast<const CharType*>(name.c_str()),
16823 name.size() + 1u);
16824 }
16825
16829 void write_bson_boolean(const string_t& name,
16830 const bool value)
16831 {
16832 write_bson_entry_header(name, 0x08);
16833 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16834 }
16835
16839 void write_bson_double(const string_t& name,
16840 const double value)
16841 {
16842 write_bson_entry_header(name, 0x01);
16843 write_number<double>(value, true);
16844 }
16845
16849 static std::size_t calc_bson_string_size(const string_t& value)
16850 {
16851 return sizeof(std::int32_t) + value.size() + 1ul;
16852 }
16853
16857 void write_bson_string(const string_t& name,
16858 const string_t& value)
16859 {
16860 write_bson_entry_header(name, 0x02);
16861
16862 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16863 oa->write_characters(
16864 reinterpret_cast<const CharType*>(value.c_str()),
16865 value.size() + 1);
16866 }
16867
16871 void write_bson_null(const string_t& name)
16872 {
16873 write_bson_entry_header(name, 0x0A);
16874 }
16875
16879 static std::size_t calc_bson_integer_size(const std::int64_t value)
16880 {
16881 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16882 ? sizeof(std::int32_t)
16883 : sizeof(std::int64_t);
16884 }
16885
16889 void write_bson_integer(const string_t& name,
16890 const std::int64_t value)
16891 {
16892 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16893 {
16894 write_bson_entry_header(name, 0x10); // int32
16895 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16896 }
16897 else
16898 {
16899 write_bson_entry_header(name, 0x12); // int64
16900 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16901 }
16902 }
16903
16907 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16908 {
16909 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16910 ? sizeof(std::int32_t)
16911 : sizeof(std::int64_t);
16912 }
16913
16917 void write_bson_unsigned(const string_t& name,
16918 const BasicJsonType& j)
16919 {
16920 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16921 {
16922 write_bson_entry_header(name, 0x10 /* int32 */);
16923 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16924 }
16925 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16926 {
16927 write_bson_entry_header(name, 0x12 /* int64 */);
16928 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16929 }
16930 else
16931 {
16932 write_bson_entry_header(name, 0x11 /* uint64 */);
16933 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16934 }
16935 }
16936
16940 void write_bson_object_entry(const string_t& name,
16941 const typename BasicJsonType::object_t& value)
16942 {
16943 write_bson_entry_header(name, 0x03); // object
16944 write_bson_object(value);
16945 }
16946
16950 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16951 {
16952 std::size_t array_index = 0ul;
16953
16954 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)
16955 {
16956 return result + calc_bson_element_size(std::to_string(array_index++), el);
16957 });
16958
16959 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16960 }
16961
16965 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16966 {
16967 return sizeof(std::int32_t) + value.size() + 1ul;
16968 }
16969
16973 void write_bson_array(const string_t& name,
16974 const typename BasicJsonType::array_t& value)
16975 {
16976 write_bson_entry_header(name, 0x04); // array
16977 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16978
16979 std::size_t array_index = 0ul;
16980
16981 for (const auto& el : value)
16982 {
16983 write_bson_element(std::to_string(array_index++), el);
16984 }
16985
16986 oa->write_character(to_char_type(0x00));
16987 }
16988
16992 void write_bson_binary(const string_t& name,
16993 const binary_t& value)
16994 {
16995 write_bson_entry_header(name, 0x05);
16996
16997 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16998 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16999
17000 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
17001 }
17002
17007 static std::size_t calc_bson_element_size(const string_t& name,
17008 const BasicJsonType& j)
17009 {
17010 const auto header_size = calc_bson_entry_header_size(name, j);
17011 switch (j.type())
17012 {
17013 case value_t::object:
17014 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
17015
17016 case value_t::array:
17017 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
17018
17019 case value_t::binary:
17020 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
17021
17022 case value_t::boolean:
17023 return header_size + 1ul;
17024
17025 case value_t::number_float:
17026 return header_size + 8ul;
17027
17028 case value_t::number_integer:
17029 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
17030
17031 case value_t::number_unsigned:
17032 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
17033
17034 case value_t::string:
17035 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
17036
17037 case value_t::null:
17038 return header_size + 0ul;
17039
17040 // LCOV_EXCL_START
17041 case value_t::discarded:
17042 default:
17043 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17044 return 0ul;
17045 // LCOV_EXCL_STOP
17046 }
17047 }
17048
17055 void write_bson_element(const string_t& name,
17056 const BasicJsonType& j)
17057 {
17058 switch (j.type())
17059 {
17060 case value_t::object:
17061 return write_bson_object_entry(name, *j.m_data.m_value.object);
17062
17063 case value_t::array:
17064 return write_bson_array(name, *j.m_data.m_value.array);
17065
17066 case value_t::binary:
17067 return write_bson_binary(name, *j.m_data.m_value.binary);
17068
17069 case value_t::boolean:
17070 return write_bson_boolean(name, j.m_data.m_value.boolean);
17071
17072 case value_t::number_float:
17073 return write_bson_double(name, j.m_data.m_value.number_float);
17074
17075 case value_t::number_integer:
17076 return write_bson_integer(name, j.m_data.m_value.number_integer);
17077
17078 case value_t::number_unsigned:
17079 return write_bson_unsigned(name, j);
17080
17081 case value_t::string:
17082 return write_bson_string(name, *j.m_data.m_value.string);
17083
17084 case value_t::null:
17085 return write_bson_null(name);
17086
17087 // LCOV_EXCL_START
17088 case value_t::discarded:
17089 default:
17090 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17091 return;
17092 // LCOV_EXCL_STOP
17093 }
17094 }
17095
17102 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17103 {
17104 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17105 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17106 {
17107 return result += calc_bson_element_size(el.first, el.second);
17108 });
17109
17110 return sizeof(std::int32_t) + document_size + 1ul;
17111 }
17112
17117 void write_bson_object(const typename BasicJsonType::object_t& value)
17118 {
17119 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17120
17121 for (const auto& el : value)
17122 {
17123 write_bson_element(el.first, el.second);
17124 }
17125
17126 oa->write_character(to_char_type(0x00));
17127 }
17128
17130 // CBOR //
17132
17133 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17134 {
17135 return to_char_type(0xFA); // Single-Precision Float
17136 }
17137
17138 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17139 {
17140 return to_char_type(0xFB); // Double-Precision Float
17141 }
17142
17144 // MsgPack //
17146
17147 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17148 {
17149 return to_char_type(0xCA); // float 32
17150 }
17151
17152 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17153 {
17154 return to_char_type(0xCB); // float 64
17155 }
17156
17158 // UBJSON //
17160
17161 // UBJSON: write number (floating point)
17162 template<typename NumberType, typename std::enable_if<
17163 std::is_floating_point<NumberType>::value, int>::type = 0>
17164 void write_number_with_ubjson_prefix(const NumberType n,
17165 const bool add_prefix,
17166 const bool use_bjdata)
17167 {
17168 if (add_prefix)
17169 {
17170 oa->write_character(get_ubjson_float_prefix(n));
17171 }
17172 write_number(n, use_bjdata);
17173 }
17174
17175 // UBJSON: write number (unsigned integer)
17176 template<typename NumberType, typename std::enable_if<
17177 std::is_unsigned<NumberType>::value, int>::type = 0>
17178 void write_number_with_ubjson_prefix(const NumberType n,
17179 const bool add_prefix,
17180 const bool use_bjdata)
17181 {
17182 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17183 {
17184 if (add_prefix)
17185 {
17186 oa->write_character(to_char_type('i')); // int8
17187 }
17188 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17189 }
17190 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17191 {
17192 if (add_prefix)
17193 {
17194 oa->write_character(to_char_type('U')); // uint8
17195 }
17196 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17197 }
17198 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17199 {
17200 if (add_prefix)
17201 {
17202 oa->write_character(to_char_type('I')); // int16
17203 }
17204 write_number(static_cast<std::int16_t>(n), use_bjdata);
17205 }
17206 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17207 {
17208 if (add_prefix)
17209 {
17210 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17211 }
17212 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17213 }
17214 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17215 {
17216 if (add_prefix)
17217 {
17218 oa->write_character(to_char_type('l')); // int32
17219 }
17220 write_number(static_cast<std::int32_t>(n), use_bjdata);
17221 }
17222 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17223 {
17224 if (add_prefix)
17225 {
17226 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17227 }
17228 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17229 }
17230 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17231 {
17232 if (add_prefix)
17233 {
17234 oa->write_character(to_char_type('L')); // int64
17235 }
17236 write_number(static_cast<std::int64_t>(n), use_bjdata);
17237 }
17238 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17239 {
17240 if (add_prefix)
17241 {
17242 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17243 }
17244 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17245 }
17246 else
17247 {
17248 if (add_prefix)
17249 {
17250 oa->write_character(to_char_type('H')); // high-precision number
17251 }
17252
17253 const auto number = BasicJsonType(n).dump();
17254 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17255 for (std::size_t i = 0; i < number.size(); ++i)
17256 {
17257 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17258 }
17259 }
17260 }
17261
17262 // UBJSON: write number (signed integer)
17263 template < typename NumberType, typename std::enable_if <
17264 std::is_signed<NumberType>::value&&
17265 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17266 void write_number_with_ubjson_prefix(const NumberType n,
17267 const bool add_prefix,
17268 const bool use_bjdata)
17269 {
17270 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17271 {
17272 if (add_prefix)
17273 {
17274 oa->write_character(to_char_type('i')); // int8
17275 }
17276 write_number(static_cast<std::int8_t>(n), use_bjdata);
17277 }
17278 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)()))
17279 {
17280 if (add_prefix)
17281 {
17282 oa->write_character(to_char_type('U')); // uint8
17283 }
17284 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17285 }
17286 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17287 {
17288 if (add_prefix)
17289 {
17290 oa->write_character(to_char_type('I')); // int16
17291 }
17292 write_number(static_cast<std::int16_t>(n), use_bjdata);
17293 }
17294 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)())))
17295 {
17296 if (add_prefix)
17297 {
17298 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17299 }
17300 write_number(static_cast<uint16_t>(n), use_bjdata);
17301 }
17302 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17303 {
17304 if (add_prefix)
17305 {
17306 oa->write_character(to_char_type('l')); // int32
17307 }
17308 write_number(static_cast<std::int32_t>(n), use_bjdata);
17309 }
17310 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)())))
17311 {
17312 if (add_prefix)
17313 {
17314 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17315 }
17316 write_number(static_cast<uint32_t>(n), use_bjdata);
17317 }
17318 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17319 {
17320 if (add_prefix)
17321 {
17322 oa->write_character(to_char_type('L')); // int64
17323 }
17324 write_number(static_cast<std::int64_t>(n), use_bjdata);
17325 }
17326 // LCOV_EXCL_START
17327 else
17328 {
17329 if (add_prefix)
17330 {
17331 oa->write_character(to_char_type('H')); // high-precision number
17332 }
17333
17334 const auto number = BasicJsonType(n).dump();
17335 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17336 for (std::size_t i = 0; i < number.size(); ++i)
17337 {
17338 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17339 }
17340 }
17341 // LCOV_EXCL_STOP
17342 }
17343
17347 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17348 {
17349 switch (j.type())
17350 {
17351 case value_t::null:
17352 return 'Z';
17353
17354 case value_t::boolean:
17355 return j.m_data.m_value.boolean ? 'T' : 'F';
17356
17357 case value_t::number_integer:
17358 {
17359 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)())
17360 {
17361 return 'i';
17362 }
17363 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)())
17364 {
17365 return 'U';
17366 }
17367 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)())
17368 {
17369 return 'I';
17370 }
17371 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)()))
17372 {
17373 return 'u';
17374 }
17375 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)())
17376 {
17377 return 'l';
17378 }
17379 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)()))
17380 {
17381 return 'm';
17382 }
17383 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)())
17384 {
17385 return 'L';
17386 }
17387 // anything else is treated as a high-precision number
17388 return 'H'; // LCOV_EXCL_LINE
17389 }
17390
17391 case value_t::number_unsigned:
17392 {
17393 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17394 {
17395 return 'i';
17396 }
17397 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17398 {
17399 return 'U';
17400 }
17401 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17402 {
17403 return 'I';
17404 }
17405 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17406 {
17407 return 'u';
17408 }
17409 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17410 {
17411 return 'l';
17412 }
17413 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17414 {
17415 return 'm';
17416 }
17417 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17418 {
17419 return 'L';
17420 }
17421 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17422 {
17423 return 'M';
17424 }
17425 // anything else is treated as a high-precision number
17426 return 'H'; // LCOV_EXCL_LINE
17427 }
17428
17429 case value_t::number_float:
17430 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17431
17432 case value_t::string:
17433 return 'S';
17434
17435 case value_t::array: // fallthrough
17436 case value_t::binary:
17437 return '[';
17438
17439 case value_t::object:
17440 return '{';
17441
17442 case value_t::discarded:
17443 default: // discarded values
17444 return 'N';
17445 }
17446 }
17447
17448 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17449 {
17450 return 'd'; // float 32
17451 }
17452
17453 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17454 {
17455 return 'D'; // float 64
17456 }
17457
17461 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17462 {
17463 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17464 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17465 {"char", 'C'}, {"byte", 'B'}
17466 };
17467
17468 string_t key = "_ArrayType_";
17469 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17470 if (it == bjdtype.end())
17471 {
17472 return true;
17473 }
17474 CharType dtype = it->second;
17475
17476 key = "_ArraySize_";
17477 std::size_t len = (value.at(key).empty() ? 0 : 1);
17478 for (const auto& el : value.at(key))
17479 {
17480 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17481 }
17482
17483 key = "_ArrayData_";
17484 if (value.at(key).size() != len)
17485 {
17486 return true;
17487 }
17488
17489 oa->write_character('[');
17490 oa->write_character('$');
17491 oa->write_character(dtype);
17492 oa->write_character('#');
17493
17494 key = "_ArraySize_";
17495 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17496
17497 key = "_ArrayData_";
17498 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17499 {
17500 for (const auto& el : value.at(key))
17501 {
17502 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17503 }
17504 }
17505 else if (dtype == 'i')
17506 {
17507 for (const auto& el : value.at(key))
17508 {
17509 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17510 }
17511 }
17512 else if (dtype == 'u')
17513 {
17514 for (const auto& el : value.at(key))
17515 {
17516 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17517 }
17518 }
17519 else if (dtype == 'I')
17520 {
17521 for (const auto& el : value.at(key))
17522 {
17523 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17524 }
17525 }
17526 else if (dtype == 'm')
17527 {
17528 for (const auto& el : value.at(key))
17529 {
17530 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17531 }
17532 }
17533 else if (dtype == 'l')
17534 {
17535 for (const auto& el : value.at(key))
17536 {
17537 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17538 }
17539 }
17540 else if (dtype == 'M')
17541 {
17542 for (const auto& el : value.at(key))
17543 {
17544 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17545 }
17546 }
17547 else if (dtype == 'L')
17548 {
17549 for (const auto& el : value.at(key))
17550 {
17551 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17552 }
17553 }
17554 else if (dtype == 'd')
17555 {
17556 for (const auto& el : value.at(key))
17557 {
17558 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17559 }
17560 }
17561 else if (dtype == 'D')
17562 {
17563 for (const auto& el : value.at(key))
17564 {
17565 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17566 }
17567 }
17568 return false;
17569 }
17570
17572 // Utility functions //
17574
17575 /*
17576 @brief write a number to output input
17577 @param[in] n number of type @a NumberType
17578 @param[in] OutputIsLittleEndian Set to true if output data is
17579 required to be little endian
17580 @tparam NumberType the type of the number
17581
17582 @note This function needs to respect the system's endianness, because bytes
17583 in CBOR, MessagePack, and UBJSON are stored in network order (big
17584 endian) and therefore need reordering on little endian systems.
17585 On the other hand, BSON and BJData use little endian and should reorder
17586 on big endian systems.
17587 */
17588 template<typename NumberType>
17589 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17590 {
17591 // step 1: write the number to an array of length NumberType
17592 std::array<CharType, sizeof(NumberType)> vec{};
17593 std::memcpy(vec.data(), &n, sizeof(NumberType));
17594
17595 // step 2: write the array to output (with possible reordering)
17596 if (is_little_endian != OutputIsLittleEndian)
17597 {
17598 // reverse byte order prior to conversion if necessary
17599 std::reverse(vec.begin(), vec.end());
17600 }
17601
17602 oa->write_characters(vec.data(), sizeof(NumberType));
17603 }
17604
17605 void write_compact_float(const number_float_t n, detail::input_format_t format)
17606 {
17607#ifdef __GNUC__
17608#pragma GCC diagnostic push
17609#pragma GCC diagnostic ignored "-Wfloat-equal"
17610#endif
17611 if (!std::isfinite(n) || ((static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17612 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17613 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))))
17614 {
17615 oa->write_character(format == detail::input_format_t::cbor
17616 ? get_cbor_float_prefix(static_cast<float>(n))
17617 : get_msgpack_float_prefix(static_cast<float>(n)));
17618 write_number(static_cast<float>(n));
17619 }
17620 else
17621 {
17622 oa->write_character(format == detail::input_format_t::cbor
17623 ? get_cbor_float_prefix(n)
17624 : get_msgpack_float_prefix(n));
17625 write_number(n);
17626 }
17627#ifdef __GNUC__
17628#pragma GCC diagnostic pop
17629#endif
17630 }
17631
17632 public:
17633 // The following to_char_type functions are implement the conversion
17634 // between uint8_t and CharType. In case CharType is not unsigned,
17635 // such a conversion is required to allow values greater than 128.
17636 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17637 template < typename C = CharType,
17638 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17639 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17640 {
17641 return *reinterpret_cast<char*>(&x);
17642 }
17643
17644 template < typename C = CharType,
17645 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17646 static CharType to_char_type(std::uint8_t x) noexcept
17647 {
17648 // The std::is_trivial trait is deprecated in C++26. The replacement is to use
17649 // std::is_trivially_copyable and std::is_trivially_default_constructible.
17650 // However, some older library implementations support std::is_trivial
17651 // but not all the std::is_trivially_* traits.
17652 // Since detecting full support across all libraries is difficult,
17653 // we use std::is_trivial unless we are using a standard where it has been deprecated.
17654 // For more details, see: https://github.com/nlohmann/json/pull/4775#issuecomment-2884361627
17655#ifdef JSON_HAS_CPP_26
17656 static_assert(std::is_trivially_copyable<CharType>::value, "CharType must be trivially copyable");
17657 static_assert(std::is_trivially_default_constructible<CharType>::value, "CharType must be trivially default constructible");
17658#else
17659 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17660#endif
17661
17662 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17663 CharType result;
17664 std::memcpy(&result, &x, sizeof(x));
17665 return result;
17666 }
17667
17668 template<typename C = CharType,
17669 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17670 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17671 {
17672 return x;
17673 }
17674
17675 template < typename InputCharType, typename C = CharType,
17676 enable_if_t <
17677 std::is_signed<C>::value &&
17678 std::is_signed<char>::value &&
17679 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17680 > * = nullptr >
17681 static constexpr CharType to_char_type(InputCharType x) noexcept
17682 {
17683 return x;
17684 }
17685
17686 private:
17688 const bool is_little_endian = little_endianness();
17689
17691 output_adapter_t<CharType> oa = nullptr;
17692};
17693
17694} // namespace detail
17695NLOHMANN_JSON_NAMESPACE_END
17696
17697// #include <nlohmann/detail/output/output_adapters.hpp>
17698
17699// #include <nlohmann/detail/output/serializer.hpp>
17700// __ _____ _____ _____
17701// __| | __| | | | JSON for Modern C++
17702// | | |__ | | | | | | version 3.12.0
17703// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17704//
17705// SPDX-FileCopyrightText: 2008, 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17706// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
17707// SPDX-License-Identifier: MIT
17708
17709
17710
17711#include <algorithm> // reverse, remove, fill, find, none_of
17712#include <array> // array
17713#include <clocale> // localeconv, lconv
17714#include <cmath> // labs, isfinite, isnan, signbit
17715#include <cstddef> // size_t, ptrdiff_t
17716#include <cstdint> // uint8_t
17717#include <cstdio> // snprintf
17718#include <limits> // numeric_limits
17719#include <string> // string, char_traits
17720#include <iomanip> // setfill, setw
17721#include <type_traits> // is_same
17722#include <utility> // move
17723
17724// #include <nlohmann/detail/conversions/to_chars.hpp>
17725// __ _____ _____ _____
17726// __| | __| | | | JSON for Modern C++
17727// | | |__ | | | | | | version 3.12.0
17728// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17729//
17730// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17731// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
17732// SPDX-License-Identifier: MIT
17733
17734
17735
17736#include <array> // array
17737#include <cmath> // signbit, isfinite
17738#include <cstdint> // intN_t, uintN_t
17739#include <cstring> // memcpy, memmove
17740#include <limits> // numeric_limits
17741#include <type_traits> // conditional
17742
17743// #include <nlohmann/detail/macro_scope.hpp>
17744
17745
17746NLOHMANN_JSON_NAMESPACE_BEGIN
17747namespace detail
17748{
17749
17769namespace dtoa_impl
17770{
17771
17772template<typename Target, typename Source>
17773Target reinterpret_bits(const Source source)
17774{
17775 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17776
17777 Target target;
17778 std::memcpy(&target, &source, sizeof(Source));
17779 return target;
17780}
17781
17782struct diyfp // f * 2^e
17783{
17784 static constexpr int kPrecision = 64; // = q
17785
17786 std::uint64_t f = 0;
17787 int e = 0;
17788
17789 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17790
17795 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17796 {
17797 JSON_ASSERT(x.e == y.e);
17798 JSON_ASSERT(x.f >= y.f);
17799
17800 return {x.f - y.f, x.e};
17801 }
17802
17807 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17808 {
17809 static_assert(kPrecision == 64, "internal error");
17810
17811 // Computes:
17812 // f = round((x.f * y.f) / 2^q)
17813 // e = x.e + y.e + q
17814
17815 // Emulate the 64-bit * 64-bit multiplication:
17816 //
17817 // p = u * v
17818 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17819 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17820 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17821 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17822 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17823 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17824 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17825 //
17826 // (Since Q might be larger than 2^32 - 1)
17827 //
17828 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17829 //
17830 // (Q_hi + H does not overflow a 64-bit int)
17831 //
17832 // = p_lo + 2^64 p_hi
17833
17834 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17835 const std::uint64_t u_hi = x.f >> 32u;
17836 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17837 const std::uint64_t v_hi = y.f >> 32u;
17838
17839 const std::uint64_t p0 = u_lo * v_lo;
17840 const std::uint64_t p1 = u_lo * v_hi;
17841 const std::uint64_t p2 = u_hi * v_lo;
17842 const std::uint64_t p3 = u_hi * v_hi;
17843
17844 const std::uint64_t p0_hi = p0 >> 32u;
17845 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17846 const std::uint64_t p1_hi = p1 >> 32u;
17847 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17848 const std::uint64_t p2_hi = p2 >> 32u;
17849
17850 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17851
17852 // The full product might now be computed as
17853 //
17854 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17855 // p_lo = p0_lo + (Q << 32)
17856 //
17857 // But in this particular case here, the full p_lo is not required.
17858 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17859 // Q_hi + 1 does not overflow).
17860
17861 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17862
17863 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17864
17865 return {h, x.e + y.e + 64};
17866 }
17867
17872 static diyfp normalize(diyfp x) noexcept
17873 {
17874 JSON_ASSERT(x.f != 0);
17875
17876 while ((x.f >> 63u) == 0)
17877 {
17878 x.f <<= 1u;
17879 x.e--;
17880 }
17881
17882 return x;
17883 }
17884
17889 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17890 {
17891 const int delta = x.e - target_exponent;
17892
17893 JSON_ASSERT(delta >= 0);
17894 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17895
17896 return {x.f << delta, target_exponent};
17897 }
17898};
17899
17901{
17902 diyfp w;
17903 diyfp minus;
17904 diyfp plus;
17905};
17906
17913template<typename FloatType>
17915{
17916 JSON_ASSERT(std::isfinite(value));
17917 JSON_ASSERT(value > 0);
17918
17919 // Convert the IEEE representation into a diyfp.
17920 //
17921 // If v is denormal:
17922 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17923 // If v is normalized:
17924 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17925
17926 static_assert(std::numeric_limits<FloatType>::is_iec559,
17927 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17928
17929 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17930 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17931 constexpr int kMinExp = 1 - kBias;
17932 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17933
17934 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17935
17936 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17937 const std::uint64_t E = bits >> (kPrecision - 1);
17938 const std::uint64_t F = bits & (kHiddenBit - 1);
17939
17940 const bool is_denormal = E == 0;
17941 const diyfp v = is_denormal
17942 ? diyfp(F, kMinExp)
17943 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17944
17945 // Compute the boundaries m- and m+ of the floating-point value
17946 // v = f * 2^e.
17947 //
17948 // Determine v- and v+, the floating-point predecessor and successor of v,
17949 // respectively.
17950 //
17951 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17952 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17953 //
17954 // v+ = v + 2^e
17955 //
17956 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17957 // between m- and m+ round to v, regardless of how the input rounding
17958 // algorithm breaks ties.
17959 //
17960 // ---+-------------+-------------+-------------+-------------+--- (A)
17961 // v- m- v m+ v+
17962 //
17963 // -----------------+------+------+-------------+-------------+--- (B)
17964 // v- m- v m+ v+
17965
17966 const bool lower_boundary_is_closer = F == 0 && E > 1;
17967 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17968 const diyfp m_minus = lower_boundary_is_closer
17969 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17970 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17971
17972 // Determine the normalized w+ = m+.
17973 const diyfp w_plus = diyfp::normalize(m_plus);
17974
17975 // Determine w- = m- such that e_(w-) = e_(w+).
17976 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17977
17978 return {diyfp::normalize(v), w_minus, w_plus};
17979}
17980
17981// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17982// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17983// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17984//
17985// alpha <= e = e_c + e_w + q <= gamma
17986//
17987// or
17988//
17989// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17990// <= f_c * f_w * 2^gamma
17991//
17992// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17993//
17994// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17995//
17996// or
17997//
17998// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17999//
18000// The choice of (alpha,gamma) determines the size of the table and the form of
18001// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
18002// in practice:
18003//
18004// The idea is to cut the number c * w = f * 2^e into two parts, which can be
18005// processed independently: An integral part p1, and a fractional part p2:
18006//
18007// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
18008// = (f div 2^-e) + (f mod 2^-e) * 2^e
18009// = p1 + p2 * 2^e
18010//
18011// The conversion of p1 into decimal form requires a series of divisions and
18012// modulos by (a power of) 10. These operations are faster for 32-bit than for
18013// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
18014// achieved by choosing
18015//
18016// -e >= 32 or e <= -32 := gamma
18017//
18018// In order to convert the fractional part
18019//
18020// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
18021//
18022// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
18023// d[-i] are extracted in order:
18024//
18025// (10 * p2) div 2^-e = d[-1]
18026// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
18027//
18028// The multiplication by 10 must not overflow. It is sufficient to choose
18029//
18030// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
18031//
18032// Since p2 = f mod 2^-e < 2^-e,
18033//
18034// -e <= 60 or e >= -60 := alpha
18035
18036constexpr int kAlpha = -60;
18037constexpr int kGamma = -32;
18038
18039struct cached_power // c = f * 2^e ~= 10^k
18040{
18041 std::uint64_t f;
18042 int e;
18043 int k;
18044};
18045
18054{
18055 // Now
18056 //
18057 // alpha <= e_c + e + q <= gamma (1)
18058 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18059 //
18060 // and since the c's are normalized, 2^(q-1) <= f_c,
18061 //
18062 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18063 // ==> 2^(alpha - e - 1) <= c
18064 //
18065 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18066 //
18067 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18068 // = ceil( (alpha - e - 1) * log_10(2) )
18069 //
18070 // From the paper:
18071 // "In theory the result of the procedure could be wrong since c is rounded,
18072 // and the computation itself is approximated [...]. In practice, however,
18073 // this simple function is sufficient."
18074 //
18075 // For IEEE double precision floating-point numbers converted into
18076 // normalized diyfp's w = f * 2^e, with q = 64,
18077 //
18078 // e >= -1022 (min IEEE exponent)
18079 // -52 (p - 1)
18080 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18081 // -11 (normalize the diyfp)
18082 // = -1137
18083 //
18084 // and
18085 //
18086 // e <= +1023 (max IEEE exponent)
18087 // -52 (p - 1)
18088 // -11 (normalize the diyfp)
18089 // = 960
18090 //
18091 // This binary exponent range [-1137,960] results in a decimal exponent
18092 // range [-307,324]. One does not need to store a cached power for each
18093 // k in this range. For each such k it suffices to find a cached power
18094 // such that the exponent of the product lies in [alpha,gamma].
18095 // This implies that the difference of the decimal exponents of adjacent
18096 // table entries must be less than or equal to
18097 //
18098 // floor( (gamma - alpha) * log_10(2) ) = 8.
18099 //
18100 // (A smaller distance gamma-alpha would require a larger table.)
18101
18102 // NB:
18103 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18104
18105 constexpr int kCachedPowersMinDecExp = -300;
18106 constexpr int kCachedPowersDecStep = 8;
18107
18108 static constexpr std::array<cached_power, 79> kCachedPowers =
18109 {
18110 {
18111 { 0xAB70FE17C79AC6CA, -1060, -300 },
18112 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18113 { 0xBE5691EF416BD60C, -1007, -284 },
18114 { 0x8DD01FAD907FFC3C, -980, -276 },
18115 { 0xD3515C2831559A83, -954, -268 },
18116 { 0x9D71AC8FADA6C9B5, -927, -260 },
18117 { 0xEA9C227723EE8BCB, -901, -252 },
18118 { 0xAECC49914078536D, -874, -244 },
18119 { 0x823C12795DB6CE57, -847, -236 },
18120 { 0xC21094364DFB5637, -821, -228 },
18121 { 0x9096EA6F3848984F, -794, -220 },
18122 { 0xD77485CB25823AC7, -768, -212 },
18123 { 0xA086CFCD97BF97F4, -741, -204 },
18124 { 0xEF340A98172AACE5, -715, -196 },
18125 { 0xB23867FB2A35B28E, -688, -188 },
18126 { 0x84C8D4DFD2C63F3B, -661, -180 },
18127 { 0xC5DD44271AD3CDBA, -635, -172 },
18128 { 0x936B9FCEBB25C996, -608, -164 },
18129 { 0xDBAC6C247D62A584, -582, -156 },
18130 { 0xA3AB66580D5FDAF6, -555, -148 },
18131 { 0xF3E2F893DEC3F126, -529, -140 },
18132 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18133 { 0x87625F056C7C4A8B, -475, -124 },
18134 { 0xC9BCFF6034C13053, -449, -116 },
18135 { 0x964E858C91BA2655, -422, -108 },
18136 { 0xDFF9772470297EBD, -396, -100 },
18137 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18138 { 0xF8A95FCF88747D94, -343, -84 },
18139 { 0xB94470938FA89BCF, -316, -76 },
18140 { 0x8A08F0F8BF0F156B, -289, -68 },
18141 { 0xCDB02555653131B6, -263, -60 },
18142 { 0x993FE2C6D07B7FAC, -236, -52 },
18143 { 0xE45C10C42A2B3B06, -210, -44 },
18144 { 0xAA242499697392D3, -183, -36 },
18145 { 0xFD87B5F28300CA0E, -157, -28 },
18146 { 0xBCE5086492111AEB, -130, -20 },
18147 { 0x8CBCCC096F5088CC, -103, -12 },
18148 { 0xD1B71758E219652C, -77, -4 },
18149 { 0x9C40000000000000, -50, 4 },
18150 { 0xE8D4A51000000000, -24, 12 },
18151 { 0xAD78EBC5AC620000, 3, 20 },
18152 { 0x813F3978F8940984, 30, 28 },
18153 { 0xC097CE7BC90715B3, 56, 36 },
18154 { 0x8F7E32CE7BEA5C70, 83, 44 },
18155 { 0xD5D238A4ABE98068, 109, 52 },
18156 { 0x9F4F2726179A2245, 136, 60 },
18157 { 0xED63A231D4C4FB27, 162, 68 },
18158 { 0xB0DE65388CC8ADA8, 189, 76 },
18159 { 0x83C7088E1AAB65DB, 216, 84 },
18160 { 0xC45D1DF942711D9A, 242, 92 },
18161 { 0x924D692CA61BE758, 269, 100 },
18162 { 0xDA01EE641A708DEA, 295, 108 },
18163 { 0xA26DA3999AEF774A, 322, 116 },
18164 { 0xF209787BB47D6B85, 348, 124 },
18165 { 0xB454E4A179DD1877, 375, 132 },
18166 { 0x865B86925B9BC5C2, 402, 140 },
18167 { 0xC83553C5C8965D3D, 428, 148 },
18168 { 0x952AB45CFA97A0B3, 455, 156 },
18169 { 0xDE469FBD99A05FE3, 481, 164 },
18170 { 0xA59BC234DB398C25, 508, 172 },
18171 { 0xF6C69A72A3989F5C, 534, 180 },
18172 { 0xB7DCBF5354E9BECE, 561, 188 },
18173 { 0x88FCF317F22241E2, 588, 196 },
18174 { 0xCC20CE9BD35C78A5, 614, 204 },
18175 { 0x98165AF37B2153DF, 641, 212 },
18176 { 0xE2A0B5DC971F303A, 667, 220 },
18177 { 0xA8D9D1535CE3B396, 694, 228 },
18178 { 0xFB9B7CD9A4A7443C, 720, 236 },
18179 { 0xBB764C4CA7A44410, 747, 244 },
18180 { 0x8BAB8EEFB6409C1A, 774, 252 },
18181 { 0xD01FEF10A657842C, 800, 260 },
18182 { 0x9B10A4E5E9913129, 827, 268 },
18183 { 0xE7109BFBA19C0C9D, 853, 276 },
18184 { 0xAC2820D9623BF429, 880, 284 },
18185 { 0x80444B5E7AA7CF85, 907, 292 },
18186 { 0xBF21E44003ACDD2D, 933, 300 },
18187 { 0x8E679C2F5E44FF8F, 960, 308 },
18188 { 0xD433179D9C8CB841, 986, 316 },
18189 { 0x9E19DB92B4E31BA9, 1013, 324 },
18190 }
18191 };
18192
18193 // This computation gives exactly the same results for k as
18194 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18195 // for |e| <= 1500, but doesn't require floating-point operations.
18196 // NB: log_10(2) ~= 78913 / 2^18
18197 JSON_ASSERT(e >= -1500);
18198 JSON_ASSERT(e <= 1500);
18199 const int f = kAlpha - e - 1;
18200 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18201
18202 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18203 JSON_ASSERT(index >= 0);
18204 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18205
18206 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18207 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18208 JSON_ASSERT(kGamma >= cached.e + e + 64);
18209
18210 return cached;
18211}
18212
18217inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18218{
18219 // LCOV_EXCL_START
18220 if (n >= 1000000000)
18221 {
18222 pow10 = 1000000000;
18223 return 10;
18224 }
18225 // LCOV_EXCL_STOP
18226 if (n >= 100000000)
18227 {
18228 pow10 = 100000000;
18229 return 9;
18230 }
18231 if (n >= 10000000)
18232 {
18233 pow10 = 10000000;
18234 return 8;
18235 }
18236 if (n >= 1000000)
18237 {
18238 pow10 = 1000000;
18239 return 7;
18240 }
18241 if (n >= 100000)
18242 {
18243 pow10 = 100000;
18244 return 6;
18245 }
18246 if (n >= 10000)
18247 {
18248 pow10 = 10000;
18249 return 5;
18250 }
18251 if (n >= 1000)
18252 {
18253 pow10 = 1000;
18254 return 4;
18255 }
18256 if (n >= 100)
18257 {
18258 pow10 = 100;
18259 return 3;
18260 }
18261 if (n >= 10)
18262 {
18263 pow10 = 10;
18264 return 2;
18265 }
18266
18267 pow10 = 1;
18268 return 1;
18269}
18270
18271inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18272 std::uint64_t rest, std::uint64_t ten_k)
18273{
18274 JSON_ASSERT(len >= 1);
18275 JSON_ASSERT(dist <= delta);
18276 JSON_ASSERT(rest <= delta);
18277 JSON_ASSERT(ten_k > 0);
18278
18279 // <--------------------------- delta ---->
18280 // <---- dist --------->
18281 // --------------[------------------+-------------------]--------------
18282 // M- w M+
18283 //
18284 // ten_k
18285 // <------>
18286 // <---- rest ---->
18287 // --------------[------------------+----+--------------]--------------
18288 // w V
18289 // = buf * 10^k
18290 //
18291 // ten_k represents a unit-in-the-last-place in the decimal representation
18292 // stored in buf.
18293 // Decrement buf by ten_k while this takes buf closer to w.
18294
18295 // The tests are written in this order to avoid overflow in unsigned
18296 // integer arithmetic.
18297
18298 while (rest < dist
18299 && delta - rest >= ten_k
18300 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18301 {
18302 JSON_ASSERT(buf[len - 1] != '0');
18303 buf[len - 1]--;
18304 rest += ten_k;
18305 }
18306}
18307
18312inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18313 diyfp M_minus, diyfp w, diyfp M_plus)
18314{
18315 static_assert(kAlpha >= -60, "internal error");
18316 static_assert(kGamma <= -32, "internal error");
18317
18318 // Generates the digits (and the exponent) of a decimal floating-point
18319 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18320 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18321 //
18322 // <--------------------------- delta ---->
18323 // <---- dist --------->
18324 // --------------[------------------+-------------------]--------------
18325 // M- w M+
18326 //
18327 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18328 // V is in [M-,M+].
18329
18330 JSON_ASSERT(M_plus.e >= kAlpha);
18331 JSON_ASSERT(M_plus.e <= kGamma);
18332
18333 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18334 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18335
18336 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18337 //
18338 // M+ = f * 2^e
18339 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18340 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18341 // = p1 + p2 * 2^e
18342
18343 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18344
18345 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.)
18346 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18347
18348 // 1)
18349 //
18350 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18351
18352 JSON_ASSERT(p1 > 0);
18353
18354 std::uint32_t pow10{};
18355 const int k = find_largest_pow10(p1, pow10);
18356
18357 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18358 //
18359 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18360 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18361 //
18362 // M+ = p1 + p2 * 2^e
18363 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18364 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18365 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18366 //
18367 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18368 //
18369 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18370 //
18371 // but stop as soon as
18372 //
18373 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18374
18375 int n = k;
18376 while (n > 0)
18377 {
18378 // Invariants:
18379 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18380 // pow10 = 10^(n-1) <= p1 < 10^n
18381 //
18382 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18383 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18384 //
18385 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18386 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18387 //
18388 JSON_ASSERT(d <= 9);
18389 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18390 //
18391 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18392 //
18393 p1 = r;
18394 n--;
18395 //
18396 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18397 // pow10 = 10^n
18398 //
18399
18400 // Now check if enough digits have been generated.
18401 // Compute
18402 //
18403 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18404 //
18405 // Note:
18406 // Since rest and delta share the same exponent e, it suffices to
18407 // compare the significands.
18408 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18409 if (rest <= delta)
18410 {
18411 // V = buffer * 10^n, with M- <= V <= M+.
18412
18413 decimal_exponent += n;
18414
18415 // We may now just stop. But instead, it looks as if the buffer
18416 // could be decremented to bring V closer to w.
18417 //
18418 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18419 // The rounding procedure works with diyfp's with an implicit
18420 // exponent of e.
18421 //
18422 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18423 //
18424 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18425 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18426
18427 return;
18428 }
18429
18430 pow10 /= 10;
18431 //
18432 // pow10 = 10^(n-1) <= p1 < 10^n
18433 // Invariants restored.
18434 }
18435
18436 // 2)
18437 //
18438 // The digits of the integral part have been generated:
18439 //
18440 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18441 // = buffer + p2 * 2^e
18442 //
18443 // Now generate the digits of the fractional part p2 * 2^e.
18444 //
18445 // Note:
18446 // No decimal point is generated: the exponent is adjusted instead.
18447 //
18448 // p2 actually represents the fraction
18449 //
18450 // p2 * 2^e
18451 // = p2 / 2^-e
18452 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18453 //
18454 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18455 //
18456 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18457 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18458 //
18459 // using
18460 //
18461 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18462 // = ( d) * 2^-e + ( r)
18463 //
18464 // or
18465 // 10^m * p2 * 2^e = d + r * 2^e
18466 //
18467 // i.e.
18468 //
18469 // M+ = buffer + p2 * 2^e
18470 // = buffer + 10^-m * (d + r * 2^e)
18471 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18472 //
18473 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18474
18475 JSON_ASSERT(p2 > delta);
18476
18477 int m = 0;
18478 for (;;)
18479 {
18480 // Invariant:
18481 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18482 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18483 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18484 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18485 //
18486 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18487 p2 *= 10;
18488 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18489 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18490 //
18491 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18492 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18493 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18494 //
18495 JSON_ASSERT(d <= 9);
18496 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18497 //
18498 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18499 //
18500 p2 = r;
18501 m++;
18502 //
18503 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18504 // Invariant restored.
18505
18506 // Check if enough digits have been generated.
18507 //
18508 // 10^-m * p2 * 2^e <= delta * 2^e
18509 // p2 * 2^e <= 10^m * delta * 2^e
18510 // p2 <= 10^m * delta
18511 delta *= 10;
18512 dist *= 10;
18513 if (p2 <= delta)
18514 {
18515 break;
18516 }
18517 }
18518
18519 // V = buffer * 10^-m, with M- <= V <= M+.
18520
18521 decimal_exponent -= m;
18522
18523 // 1 ulp in the decimal representation is now 10^-m.
18524 // Since delta and dist are now scaled by 10^m, we need to do the
18525 // same with ulp in order to keep the units in sync.
18526 //
18527 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18528 //
18529 const std::uint64_t ten_m = one.f;
18530 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18531
18532 // By construction this algorithm generates the shortest possible decimal
18533 // number (Loitsch, Theorem 6.2) which rounds back to w.
18534 // For an input number of precision p, at least
18535 //
18536 // N = 1 + ceil(p * log_10(2))
18537 //
18538 // decimal digits are sufficient to identify all binary floating-point
18539 // numbers (Matula, "In-and-Out conversions").
18540 // This implies that the algorithm does not produce more than N decimal
18541 // digits.
18542 //
18543 // N = 17 for p = 53 (IEEE double precision)
18544 // N = 9 for p = 24 (IEEE single precision)
18545}
18546
18552JSON_HEDLEY_NON_NULL(1)
18553inline void grisu2(char* buf, int& len, int& decimal_exponent,
18554 diyfp m_minus, diyfp v, diyfp m_plus)
18555{
18556 JSON_ASSERT(m_plus.e == m_minus.e);
18557 JSON_ASSERT(m_plus.e == v.e);
18558
18559 // --------(-----------------------+-----------------------)-------- (A)
18560 // m- v m+
18561 //
18562 // --------------------(-----------+-----------------------)-------- (B)
18563 // m- v m+
18564 //
18565 // First scale v (and m- and m+) such that the exponent is in the range
18566 // [alpha, gamma].
18567
18568 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18569
18570 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18571
18572 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18573 const diyfp w = diyfp::mul(v, c_minus_k);
18574 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18575 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18576
18577 // ----(---+---)---------------(---+---)---------------(---+---)----
18578 // w- w w+
18579 // = c*m- = c*v = c*m+
18580 //
18581 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18582 // w+ are now off by a small amount.
18583 // In fact:
18584 //
18585 // w - v * 10^k < 1 ulp
18586 //
18587 // To account for this inaccuracy, add resp. subtract 1 ulp.
18588 //
18589 // --------+---[---------------(---+---)---------------]---+--------
18590 // w- M- w M+ w+
18591 //
18592 // Now any number in [M-, M+] (bounds included) will round to w when input,
18593 // regardless of how the input rounding algorithm breaks ties.
18594 //
18595 // And digit_gen generates the shortest possible such number in [M-, M+].
18596 // Note that this does not mean that Grisu2 always generates the shortest
18597 // possible number in the interval (m-, m+).
18598 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18599 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18600
18601 decimal_exponent = -cached.k; // = -(-k) = k
18602
18603 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18604}
18605
18611template<typename FloatType>
18612JSON_HEDLEY_NON_NULL(1)
18613void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18614{
18615 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18616 "internal error: not enough precision");
18617
18618 JSON_ASSERT(std::isfinite(value));
18619 JSON_ASSERT(value > 0);
18620
18621 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18622 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18623 // decimal representations are not exactly "short".
18624 //
18625 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18626 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18627 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18628 // does.
18629 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18630 // representation using the corresponding std::from_chars function recovers value exactly". That
18631 // indicates that single precision floating-point numbers should be recovered using
18632 // 'std::strtof'.
18633 //
18634 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18635 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18636 // value is off by 1 ulp.
18637#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18638 const boundaries w = compute_boundaries(static_cast<double>(value));
18639#else
18640 const boundaries w = compute_boundaries(value);
18641#endif
18642
18643 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18644}
18645
18651JSON_HEDLEY_NON_NULL(1)
18652JSON_HEDLEY_RETURNS_NON_NULL
18653inline char* append_exponent(char* buf, int e)
18654{
18655 JSON_ASSERT(e > -1000);
18656 JSON_ASSERT(e < 1000);
18657
18658 if (e < 0)
18659 {
18660 e = -e;
18661 *buf++ = '-';
18662 }
18663 else
18664 {
18665 *buf++ = '+';
18666 }
18667
18668 auto k = static_cast<std::uint32_t>(e);
18669 if (k < 10)
18670 {
18671 // Always print at least two digits in the exponent.
18672 // This is for compatibility with printf("%g").
18673 *buf++ = '0';
18674 *buf++ = static_cast<char>('0' + k);
18675 }
18676 else if (k < 100)
18677 {
18678 *buf++ = static_cast<char>('0' + (k / 10));
18679 k %= 10;
18680 *buf++ = static_cast<char>('0' + k);
18681 }
18682 else
18683 {
18684 *buf++ = static_cast<char>('0' + (k / 100));
18685 k %= 100;
18686 *buf++ = static_cast<char>('0' + (k / 10));
18687 k %= 10;
18688 *buf++ = static_cast<char>('0' + k);
18689 }
18690
18691 return buf;
18692}
18693
18703JSON_HEDLEY_NON_NULL(1)
18704JSON_HEDLEY_RETURNS_NON_NULL
18705inline char* format_buffer(char* buf, int len, int decimal_exponent,
18706 int min_exp, int max_exp)
18707{
18708 JSON_ASSERT(min_exp < 0);
18709 JSON_ASSERT(max_exp > 0);
18710
18711 const int k = len;
18712 const int n = len + decimal_exponent;
18713
18714 // v = buf * 10^(n-k)
18715 // k is the length of the buffer (number of decimal digits)
18716 // n is the position of the decimal point relative to the start of the buffer.
18717
18718 if (k <= n && n <= max_exp)
18719 {
18720 // digits[000]
18721 // len <= max_exp + 2
18722
18723 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18724 // Make it look like a floating-point number (#362, #378)
18725 buf[n + 0] = '.';
18726 buf[n + 1] = '0';
18727 return buf + (static_cast<size_t>(n) + 2);
18728 }
18729
18730 if (0 < n && n <= max_exp)
18731 {
18732 // dig.its
18733 // len <= max_digits10 + 1
18734
18735 JSON_ASSERT(k > n);
18736
18737 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18738 buf[n] = '.';
18739 return buf + (static_cast<size_t>(k) + 1U);
18740 }
18741
18742 if (min_exp < n && n <= 0)
18743 {
18744 // 0.[000]digits
18745 // len <= 2 + (-min_exp - 1) + max_digits10
18746
18747 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18748 buf[0] = '0';
18749 buf[1] = '.';
18750 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18751 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18752 }
18753
18754 if (k == 1)
18755 {
18756 // dE+123
18757 // len <= 1 + 5
18758
18759 buf += 1;
18760 }
18761 else
18762 {
18763 // d.igitsE+123
18764 // len <= max_digits10 + 1 + 5
18765
18766 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18767 buf[1] = '.';
18768 buf += 1 + static_cast<size_t>(k);
18769 }
18770
18771 *buf++ = 'e';
18772 return append_exponent(buf, n - 1);
18773}
18774
18775} // namespace dtoa_impl
18776
18787template<typename FloatType>
18788JSON_HEDLEY_NON_NULL(1, 2)
18789JSON_HEDLEY_RETURNS_NON_NULL
18790char* to_chars(char* first, const char* last, FloatType value)
18791{
18792 static_cast<void>(last); // maybe unused - fix warning
18793 JSON_ASSERT(std::isfinite(value));
18794
18795 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18796 if (std::signbit(value))
18797 {
18798 value = -value;
18799 *first++ = '-';
18800 }
18801
18802#ifdef __GNUC__
18803#pragma GCC diagnostic push
18804#pragma GCC diagnostic ignored "-Wfloat-equal"
18805#endif
18806 if (value == 0) // +-0
18807 {
18808 *first++ = '0';
18809 // Make it look like a floating-point number (#362, #378)
18810 *first++ = '.';
18811 *first++ = '0';
18812 return first;
18813 }
18814#ifdef __GNUC__
18815#pragma GCC diagnostic pop
18816#endif
18817
18818 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18819
18820 // Compute v = buffer * 10^decimal_exponent.
18821 // The decimal digits are stored in the buffer, which needs to be interpreted
18822 // as an unsigned decimal integer.
18823 // len is the length of the buffer, i.e., the number of decimal digits.
18824 int len = 0;
18825 int decimal_exponent = 0;
18826 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18827
18828 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18829
18830 // Format the buffer like printf("%.*g", prec, value)
18831 constexpr int kMinExp = -4;
18832 // Use digits10 here to increase compatibility with version 2.
18833 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18834
18835 JSON_ASSERT(last - first >= kMaxExp + 2);
18836 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18837 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18838
18839 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18840}
18841
18842} // namespace detail
18843NLOHMANN_JSON_NAMESPACE_END
18844
18845// #include <nlohmann/detail/exceptions.hpp>
18846
18847// #include <nlohmann/detail/macro_scope.hpp>
18848
18849// #include <nlohmann/detail/meta/cpp_future.hpp>
18850
18851// #include <nlohmann/detail/output/binary_writer.hpp>
18852
18853// #include <nlohmann/detail/output/output_adapters.hpp>
18854
18855// #include <nlohmann/detail/string_concat.hpp>
18856
18857// #include <nlohmann/detail/value_t.hpp>
18858
18859
18860NLOHMANN_JSON_NAMESPACE_BEGIN
18861namespace detail
18862{
18863
18865// serialization //
18867
18870{
18874};
18875
18876template<typename BasicJsonType>
18878{
18879 using string_t = typename BasicJsonType::string_t;
18880 using number_float_t = typename BasicJsonType::number_float_t;
18881 using number_integer_t = typename BasicJsonType::number_integer_t;
18882 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18883 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18884 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18885 static constexpr std::uint8_t UTF8_REJECT = 1;
18886
18887 public:
18895 : o(std::move(s))
18896 , loc(std::localeconv())
18897 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18898 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18899 , indent_char(ichar)
18901 , error_handler(error_handler_)
18902 {}
18903
18904 // deleted because of pointer members
18905 serializer(const serializer&) = delete;
18906 serializer& operator=(const serializer&) = delete;
18907 serializer(serializer&&) = delete;
18908 serializer& operator=(serializer&&) = delete;
18909 ~serializer() = default;
18910
18933 void dump(const BasicJsonType& val,
18934 const bool pretty_print,
18935 const bool ensure_ascii,
18936 const unsigned int indent_step,
18937 const unsigned int current_indent = 0)
18938 {
18939 switch (val.m_data.m_type)
18940 {
18941 case value_t::object:
18942 {
18943 if (val.m_data.m_value.object->empty())
18944 {
18945 o->write_characters("{}", 2);
18946 return;
18947 }
18948
18949 if (pretty_print)
18950 {
18951 o->write_characters("{\n", 2);
18952
18953 // variable to hold indentation for recursive calls
18954 const auto new_indent = current_indent + indent_step;
18955 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18956 {
18957 indent_string.resize(indent_string.size() * 2, ' ');
18958 }
18959
18960 // first n-1 elements
18961 auto i = val.m_data.m_value.object->cbegin();
18962 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18963 {
18964 o->write_characters(indent_string.c_str(), new_indent);
18965 o->write_character('\"');
18966 dump_escaped(i->first, ensure_ascii);
18967 o->write_characters("\": ", 3);
18968 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18969 o->write_characters(",\n", 2);
18970 }
18971
18972 // last element
18973 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18974 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18975 o->write_characters(indent_string.c_str(), new_indent);
18976 o->write_character('\"');
18977 dump_escaped(i->first, ensure_ascii);
18978 o->write_characters("\": ", 3);
18979 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18980
18981 o->write_character('\n');
18982 o->write_characters(indent_string.c_str(), current_indent);
18983 o->write_character('}');
18984 }
18985 else
18986 {
18987 o->write_character('{');
18988
18989 // first n-1 elements
18990 auto i = val.m_data.m_value.object->cbegin();
18991 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18992 {
18993 o->write_character('\"');
18994 dump_escaped(i->first, ensure_ascii);
18995 o->write_characters("\":", 2);
18996 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18997 o->write_character(',');
18998 }
18999
19000 // last element
19001 JSON_ASSERT(i != val.m_data.m_value.object->cend());
19002 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
19003 o->write_character('\"');
19004 dump_escaped(i->first, ensure_ascii);
19005 o->write_characters("\":", 2);
19006 dump(i->second, false, ensure_ascii, indent_step, current_indent);
19007
19008 o->write_character('}');
19009 }
19010
19011 return;
19012 }
19013
19014 case value_t::array:
19015 {
19016 if (val.m_data.m_value.array->empty())
19017 {
19018 o->write_characters("[]", 2);
19019 return;
19020 }
19021
19022 if (pretty_print)
19023 {
19024 o->write_characters("[\n", 2);
19025
19026 // variable to hold indentation for recursive calls
19027 const auto new_indent = current_indent + indent_step;
19028 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19029 {
19030 indent_string.resize(indent_string.size() * 2, ' ');
19031 }
19032
19033 // first n-1 elements
19034 for (auto i = val.m_data.m_value.array->cbegin();
19035 i != val.m_data.m_value.array->cend() - 1; ++i)
19036 {
19037 o->write_characters(indent_string.c_str(), new_indent);
19038 dump(*i, true, ensure_ascii, indent_step, new_indent);
19039 o->write_characters(",\n", 2);
19040 }
19041
19042 // last element
19043 JSON_ASSERT(!val.m_data.m_value.array->empty());
19044 o->write_characters(indent_string.c_str(), new_indent);
19045 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
19046
19047 o->write_character('\n');
19048 o->write_characters(indent_string.c_str(), current_indent);
19049 o->write_character(']');
19050 }
19051 else
19052 {
19053 o->write_character('[');
19054
19055 // first n-1 elements
19056 for (auto i = val.m_data.m_value.array->cbegin();
19057 i != val.m_data.m_value.array->cend() - 1; ++i)
19058 {
19059 dump(*i, false, ensure_ascii, indent_step, current_indent);
19060 o->write_character(',');
19061 }
19062
19063 // last element
19064 JSON_ASSERT(!val.m_data.m_value.array->empty());
19065 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19066
19067 o->write_character(']');
19068 }
19069
19070 return;
19071 }
19072
19073 case value_t::string:
19074 {
19075 o->write_character('\"');
19076 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19077 o->write_character('\"');
19078 return;
19079 }
19080
19081 case value_t::binary:
19082 {
19083 if (pretty_print)
19084 {
19085 o->write_characters("{\n", 2);
19086
19087 // variable to hold indentation for recursive calls
19088 const auto new_indent = current_indent + indent_step;
19089 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19090 {
19091 indent_string.resize(indent_string.size() * 2, ' ');
19092 }
19093
19094 o->write_characters(indent_string.c_str(), new_indent);
19095
19096 o->write_characters("\"bytes\": [", 10);
19097
19098 if (!val.m_data.m_value.binary->empty())
19099 {
19100 for (auto i = val.m_data.m_value.binary->cbegin();
19101 i != val.m_data.m_value.binary->cend() - 1; ++i)
19102 {
19103 dump_integer(*i);
19104 o->write_characters(", ", 2);
19105 }
19106 dump_integer(val.m_data.m_value.binary->back());
19107 }
19108
19109 o->write_characters("],\n", 3);
19110 o->write_characters(indent_string.c_str(), new_indent);
19111
19112 o->write_characters("\"subtype\": ", 11);
19113 if (val.m_data.m_value.binary->has_subtype())
19114 {
19115 dump_integer(val.m_data.m_value.binary->subtype());
19116 }
19117 else
19118 {
19119 o->write_characters("null", 4);
19120 }
19121 o->write_character('\n');
19122 o->write_characters(indent_string.c_str(), current_indent);
19123 o->write_character('}');
19124 }
19125 else
19126 {
19127 o->write_characters("{\"bytes\":[", 10);
19128
19129 if (!val.m_data.m_value.binary->empty())
19130 {
19131 for (auto i = val.m_data.m_value.binary->cbegin();
19132 i != val.m_data.m_value.binary->cend() - 1; ++i)
19133 {
19134 dump_integer(*i);
19135 o->write_character(',');
19136 }
19137 dump_integer(val.m_data.m_value.binary->back());
19138 }
19139
19140 o->write_characters("],\"subtype\":", 12);
19141 if (val.m_data.m_value.binary->has_subtype())
19142 {
19143 dump_integer(val.m_data.m_value.binary->subtype());
19144 o->write_character('}');
19145 }
19146 else
19147 {
19148 o->write_characters("null}", 5);
19149 }
19150 }
19151 return;
19152 }
19153
19154 case value_t::boolean:
19155 {
19156 if (val.m_data.m_value.boolean)
19157 {
19158 o->write_characters("true", 4);
19159 }
19160 else
19161 {
19162 o->write_characters("false", 5);
19163 }
19164 return;
19165 }
19166
19168 {
19169 dump_integer(val.m_data.m_value.number_integer);
19170 return;
19171 }
19172
19174 {
19175 dump_integer(val.m_data.m_value.number_unsigned);
19176 return;
19177 }
19178
19180 {
19181 dump_float(val.m_data.m_value.number_float);
19182 return;
19183 }
19184
19185 case value_t::discarded:
19186 {
19187 o->write_characters("<discarded>", 11);
19188 return;
19189 }
19190
19191 case value_t::null:
19192 {
19193 o->write_characters("null", 4);
19194 return;
19195 }
19196
19197 default: // LCOV_EXCL_LINE
19198 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19199 }
19200 }
19201
19202 JSON_PRIVATE_UNLESS_TESTED:
19217 void dump_escaped(const string_t& s, const bool ensure_ascii)
19218 {
19219 std::uint32_t codepoint{};
19220 std::uint8_t state = UTF8_ACCEPT;
19221 std::size_t bytes = 0; // number of bytes written to string_buffer
19222
19223 // number of bytes written at the point of the last valid byte
19224 std::size_t bytes_after_last_accept = 0;
19225 std::size_t undumped_chars = 0;
19226
19227 for (std::size_t i = 0; i < s.size(); ++i)
19228 {
19229 const auto byte = static_cast<std::uint8_t>(s[i]);
19230
19231 switch (decode(state, codepoint, byte))
19232 {
19233 case UTF8_ACCEPT: // decode found a new code point
19234 {
19235 switch (codepoint)
19236 {
19237 case 0x08: // backspace
19238 {
19239 string_buffer[bytes++] = '\\';
19240 string_buffer[bytes++] = 'b';
19241 break;
19242 }
19243
19244 case 0x09: // horizontal tab
19245 {
19246 string_buffer[bytes++] = '\\';
19247 string_buffer[bytes++] = 't';
19248 break;
19249 }
19250
19251 case 0x0A: // newline
19252 {
19253 string_buffer[bytes++] = '\\';
19254 string_buffer[bytes++] = 'n';
19255 break;
19256 }
19257
19258 case 0x0C: // formfeed
19259 {
19260 string_buffer[bytes++] = '\\';
19261 string_buffer[bytes++] = 'f';
19262 break;
19263 }
19264
19265 case 0x0D: // carriage return
19266 {
19267 string_buffer[bytes++] = '\\';
19268 string_buffer[bytes++] = 'r';
19269 break;
19270 }
19271
19272 case 0x22: // quotation mark
19273 {
19274 string_buffer[bytes++] = '\\';
19275 string_buffer[bytes++] = '\"';
19276 break;
19277 }
19278
19279 case 0x5C: // reverse solidus
19280 {
19281 string_buffer[bytes++] = '\\';
19282 string_buffer[bytes++] = '\\';
19283 break;
19284 }
19285
19286 default:
19287 {
19288 // escape control characters (0x00..0x1F) or, if
19289 // ensure_ascii parameter is used, non-ASCII characters
19290 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19291 {
19292 if (codepoint <= 0xFFFF)
19293 {
19294 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19295 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19296 static_cast<std::uint16_t>(codepoint)));
19297 bytes += 6;
19298 }
19299 else
19300 {
19301 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19302 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19303 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19304 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19305 bytes += 12;
19306 }
19307 }
19308 else
19309 {
19310 // copy byte to buffer (all previous bytes
19311 // been copied have in default case above)
19312 string_buffer[bytes++] = s[i];
19313 }
19314 break;
19315 }
19316 }
19317
19318 // write buffer and reset index; there must be 13 bytes
19319 // left, as this is the maximal number of bytes to be
19320 // written ("\uxxxx\uxxxx\0") for one code point
19321 if (string_buffer.size() - bytes < 13)
19322 {
19323 o->write_characters(string_buffer.data(), bytes);
19324 bytes = 0;
19325 }
19326
19327 // remember the byte position of this accept
19328 bytes_after_last_accept = bytes;
19329 undumped_chars = 0;
19330 break;
19331 }
19332
19333 case UTF8_REJECT: // decode found invalid UTF-8 byte
19334 {
19335 switch (error_handler)
19336 {
19337 case error_handler_t::strict:
19338 {
19339 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19340 }
19341
19342 case error_handler_t::ignore:
19343 case error_handler_t::replace:
19344 {
19345 // in case we saw this character the first time, we
19346 // would like to read it again, because the byte
19347 // may be OK for itself, but just not OK for the
19348 // previous sequence
19349 if (undumped_chars > 0)
19350 {
19351 --i;
19352 }
19353
19354 // reset length buffer to the last accepted index;
19355 // thus removing/ignoring the invalid characters
19356 bytes = bytes_after_last_accept;
19357
19358 if (error_handler == error_handler_t::replace)
19359 {
19360 // add a replacement character
19361 if (ensure_ascii)
19362 {
19363 string_buffer[bytes++] = '\\';
19364 string_buffer[bytes++] = 'u';
19365 string_buffer[bytes++] = 'f';
19366 string_buffer[bytes++] = 'f';
19367 string_buffer[bytes++] = 'f';
19368 string_buffer[bytes++] = 'd';
19369 }
19370 else
19371 {
19372 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19373 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19374 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19375 }
19376
19377 // write buffer and reset index; there must be 13 bytes
19378 // left, as this is the maximal number of bytes to be
19379 // written ("\uxxxx\uxxxx\0") for one code point
19380 if (string_buffer.size() - bytes < 13)
19381 {
19382 o->write_characters(string_buffer.data(), bytes);
19383 bytes = 0;
19384 }
19385
19386 bytes_after_last_accept = bytes;
19387 }
19388
19389 undumped_chars = 0;
19390
19391 // continue processing the string
19392 state = UTF8_ACCEPT;
19393 break;
19394 }
19395
19396 default: // LCOV_EXCL_LINE
19397 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19398 }
19399 break;
19400 }
19401
19402 default: // decode found yet incomplete multibyte code point
19403 {
19404 if (!ensure_ascii)
19405 {
19406 // code point will not be escaped - copy byte to buffer
19407 string_buffer[bytes++] = s[i];
19408 }
19409 ++undumped_chars;
19410 break;
19411 }
19412 }
19413 }
19414
19415 // we finished processing the string
19416 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19417 {
19418 // write buffer
19419 if (bytes > 0)
19420 {
19421 o->write_characters(string_buffer.data(), bytes);
19422 }
19423 }
19424 else
19425 {
19426 // we finish reading, but do not accept: string was incomplete
19427 switch (error_handler)
19428 {
19429 case error_handler_t::strict:
19430 {
19431 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));
19432 }
19433
19434 case error_handler_t::ignore:
19435 {
19436 // write all accepted bytes
19437 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19438 break;
19439 }
19440
19441 case error_handler_t::replace:
19442 {
19443 // write all accepted bytes
19444 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19445 // add a replacement character
19446 if (ensure_ascii)
19447 {
19448 o->write_characters("\\ufffd", 6);
19449 }
19450 else
19451 {
19452 o->write_characters("\xEF\xBF\xBD", 3);
19453 }
19454 break;
19455 }
19456
19457 default: // LCOV_EXCL_LINE
19458 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19459 }
19460 }
19461 }
19462
19463 private:
19472 unsigned int count_digits(number_unsigned_t x) noexcept
19473 {
19474 unsigned int n_digits = 1;
19475 for (;;)
19476 {
19477 if (x < 10)
19478 {
19479 return n_digits;
19480 }
19481 if (x < 100)
19482 {
19483 return n_digits + 1;
19484 }
19485 if (x < 1000)
19486 {
19487 return n_digits + 2;
19488 }
19489 if (x < 10000)
19490 {
19491 return n_digits + 3;
19492 }
19493 x = x / 10000u;
19494 n_digits += 4;
19495 }
19496 }
19497
19503 static std::string hex_bytes(std::uint8_t byte)
19504 {
19505 std::string result = "FF";
19506 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19507 result[0] = nibble_to_hex[byte / 16];
19508 result[1] = nibble_to_hex[byte % 16];
19509 return result;
19510 }
19511
19512 // templates to avoid warnings about useless casts
19513 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19514 bool is_negative_number(NumberType x)
19515 {
19516 return x < 0;
19517 }
19518
19519 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19520 bool is_negative_number(NumberType /*unused*/)
19521 {
19522 return false;
19523 }
19524
19534 template < typename NumberType, detail::enable_if_t <
19535 std::is_integral<NumberType>::value ||
19536 std::is_same<NumberType, number_unsigned_t>::value ||
19537 std::is_same<NumberType, number_integer_t>::value ||
19538 std::is_same<NumberType, binary_char_t>::value,
19539 int > = 0 >
19540 void dump_integer(NumberType x)
19541 {
19542 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19543 {
19544 {
19545 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19546 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19547 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19548 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19549 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19550 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19551 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19552 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19553 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19554 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19555 }
19556 };
19557
19558 // special case for "0"
19559 if (x == 0)
19560 {
19561 o->write_character('0');
19562 return;
19563 }
19564
19565 // use a pointer to fill the buffer
19566 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19567
19568 number_unsigned_t abs_value;
19569
19570 unsigned int n_chars{};
19571
19572 if (is_negative_number(x))
19573 {
19574 *buffer_ptr = '-';
19575 abs_value = remove_sign(static_cast<number_integer_t>(x));
19576
19577 // account one more byte for the minus sign
19578 n_chars = 1 + count_digits(abs_value);
19579 }
19580 else
19581 {
19582 abs_value = static_cast<number_unsigned_t>(x);
19583 n_chars = count_digits(abs_value);
19584 }
19585
19586 // spare 1 byte for '\0'
19587 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19588
19589 // jump to the end to generate the string from backward,
19590 // so we later avoid reversing the result
19591 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19592
19593 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19594 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19595 while (abs_value >= 100)
19596 {
19597 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19598 abs_value /= 100;
19599 *(--buffer_ptr) = digits_to_99[digits_index][1];
19600 *(--buffer_ptr) = digits_to_99[digits_index][0];
19601 }
19602
19603 if (abs_value >= 10)
19604 {
19605 const auto digits_index = static_cast<unsigned>(abs_value);
19606 *(--buffer_ptr) = digits_to_99[digits_index][1];
19607 *(--buffer_ptr) = digits_to_99[digits_index][0];
19608 }
19609 else
19610 {
19611 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19612 }
19613
19614 o->write_characters(number_buffer.data(), n_chars);
19615 }
19616
19625 void dump_float(number_float_t x)
19626 {
19627 // NaN / inf
19628 if (!std::isfinite(x))
19629 {
19630 o->write_characters("null", 4);
19631 return;
19632 }
19633
19634 // If number_float_t is an IEEE-754 single or double precision number,
19635 // use the Grisu2 algorithm to produce short numbers which are
19636 // guaranteed to round-trip, using strtof and strtod, resp.
19637 //
19638 // NB: The test below works if <long double> == <double>.
19639 static constexpr bool is_ieee_single_or_double
19640 = (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) ||
19641 (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);
19642
19643 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19644 }
19645
19646 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19647 {
19648 auto* begin = number_buffer.data();
19649 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19650
19651 o->write_characters(begin, static_cast<size_t>(end - begin));
19652 }
19653
19654 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19655 {
19656 // get the number of digits for a float -> text -> float round-trip
19657 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19658
19659 // the actual conversion
19660 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19661 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19662
19663 // negative value indicates an error
19664 JSON_ASSERT(len > 0);
19665 // check if the buffer was large enough
19666 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19667
19668 // erase thousands separators
19669 if (thousands_sep != '\0')
19670 {
19671 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19672 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19673 std::fill(end, number_buffer.end(), '\0');
19674 JSON_ASSERT((end - number_buffer.begin()) <= len);
19675 len = (end - number_buffer.begin());
19676 }
19677
19678 // convert decimal point to '.'
19679 if (decimal_point != '\0' && decimal_point != '.')
19680 {
19681 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19682 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19683 if (dec_pos != number_buffer.end())
19684 {
19685 *dec_pos = '.';
19686 }
19687 }
19688
19689 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19690
19691 // determine if we need to append ".0"
19692 const bool value_is_int_like =
19693 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19694 [](char c)
19695 {
19696 return c == '.' || c == 'e';
19697 });
19698
19699 if (value_is_int_like)
19700 {
19701 o->write_characters(".0", 2);
19702 }
19703 }
19704
19726 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19727 {
19728 static const std::array<std::uint8_t, 400> utf8d =
19729 {
19730 {
19731 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
19732 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
19733 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
19734 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
19735 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
19736 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
19737 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
19738 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19739 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19740 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19741 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
19742 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
19743 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
19744 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
19745 }
19746 };
19747
19748 JSON_ASSERT(byte < utf8d.size());
19749 const std::uint8_t type = utf8d[byte];
19750
19751 codep = (state != UTF8_ACCEPT)
19752 ? (byte & 0x3fu) | (codep << 6u)
19753 : (0xFFu >> type) & (byte);
19754
19755 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19756 JSON_ASSERT(index < utf8d.size());
19757 state = utf8d[index];
19758 return state;
19759 }
19760
19761 /*
19762 * Overload to make the compiler happy while it is instantiating
19763 * dump_integer for number_unsigned_t.
19764 * Must never be called.
19765 */
19766 number_unsigned_t remove_sign(number_unsigned_t x)
19767 {
19768 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19769 return x; // LCOV_EXCL_LINE
19770 }
19771
19772 /*
19773 * Helper function for dump_integer
19774 *
19775 * This function takes a negative signed integer and returns its absolute
19776 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19777 * cannot directly remove the sign of an arbitrary signed integer as the
19778 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19779 * #1708 for details.
19780 */
19781 number_unsigned_t remove_sign(number_integer_t x) noexcept
19782 {
19783 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19784 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19785 }
19786
19787 private:
19789 output_adapter_t<char> o = nullptr;
19790
19792 std::array<char, 64> number_buffer{{}};
19793
19795 const std::lconv* loc = nullptr;
19797 const char thousands_sep = '\0';
19799 const char decimal_point = '\0';
19800
19802 std::array<char, 512> string_buffer{{}};
19803
19805 const char indent_char;
19808
19811};
19812
19813} // namespace detail
19814NLOHMANN_JSON_NAMESPACE_END
19815
19816// #include <nlohmann/detail/value_t.hpp>
19817
19818// #include <nlohmann/json_fwd.hpp>
19819
19820// #include <nlohmann/ordered_map.hpp>
19821// __ _____ _____ _____
19822// __| | __| | | | JSON for Modern C++
19823// | | |__ | | | | | | version 3.12.0
19824// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19825//
19826// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
19827// SPDX-License-Identifier: MIT
19828
19829
19830
19831#include <functional> // equal_to, less
19832#include <initializer_list> // initializer_list
19833#include <iterator> // input_iterator_tag, iterator_traits
19834#include <memory> // allocator
19835#include <stdexcept> // for out_of_range
19836#include <type_traits> // enable_if, is_convertible
19837#include <utility> // pair
19838#include <vector> // vector
19839
19840// #include <nlohmann/detail/macro_scope.hpp>
19841
19842// #include <nlohmann/detail/meta/type_traits.hpp>
19843
19844
19845NLOHMANN_JSON_NAMESPACE_BEGIN
19846
19849template <class Key, class T, class IgnoredLess = std::less<Key>,
19850 class Allocator = std::allocator<std::pair<const Key, T>>>
19851 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19852{
19853 using key_type = Key;
19854 using mapped_type = T;
19855 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19856 using iterator = typename Container::iterator;
19857 using const_iterator = typename Container::const_iterator;
19858 using size_type = typename Container::size_type;
19859 using value_type = typename Container::value_type;
19860#ifdef JSON_HAS_CPP_14
19861 using key_compare = std::equal_to<>;
19862#else
19863 using key_compare = std::equal_to<Key>;
19864#endif
19865
19866 // Explicit constructors instead of `using Container::Container`
19867 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19868 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19869 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19870 template <class It>
19871 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19872 : Container{first, last, alloc} {}
19873 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19874 : Container{init, alloc} {}
19875
19876 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19877 {
19878 for (auto it = this->begin(); it != this->end(); ++it)
19879 {
19880 if (m_compare(it->first, key))
19881 {
19882 return {it, false};
19883 }
19884 }
19885 Container::emplace_back(key, std::forward<T>(t));
19886 return {std::prev(this->end()), true};
19887 }
19888
19889 template<class KeyType, detail::enable_if_t<
19890 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19891 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19892 {
19893 for (auto it = this->begin(); it != this->end(); ++it)
19894 {
19895 if (m_compare(it->first, key))
19896 {
19897 return {it, false};
19898 }
19899 }
19900 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19901 return {std::prev(this->end()), true};
19902 }
19903
19904 T& operator[](const key_type& key)
19905 {
19906 return emplace(key, T{}).first->second;
19907 }
19908
19909 template<class KeyType, detail::enable_if_t<
19910 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19911 T & operator[](KeyType && key)
19912 {
19913 return emplace(std::forward<KeyType>(key), T{}).first->second;
19914 }
19915
19916 const T& operator[](const key_type& key) const
19917 {
19918 return at(key);
19919 }
19920
19921 template<class KeyType, detail::enable_if_t<
19922 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19923 const T & operator[](KeyType && key) const
19924 {
19925 return at(std::forward<KeyType>(key));
19926 }
19927
19928 T& at(const key_type& key)
19929 {
19930 for (auto it = this->begin(); it != this->end(); ++it)
19931 {
19932 if (m_compare(it->first, key))
19933 {
19934 return it->second;
19935 }
19936 }
19937
19938 JSON_THROW(std::out_of_range("key not found"));
19939 }
19940
19941 template<class KeyType, detail::enable_if_t<
19942 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19943 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19944 {
19945 for (auto it = this->begin(); it != this->end(); ++it)
19946 {
19947 if (m_compare(it->first, key))
19948 {
19949 return it->second;
19950 }
19951 }
19952
19953 JSON_THROW(std::out_of_range("key not found"));
19954 }
19955
19956 const T& at(const key_type& key) const
19957 {
19958 for (auto it = this->begin(); it != this->end(); ++it)
19959 {
19960 if (m_compare(it->first, key))
19961 {
19962 return it->second;
19963 }
19964 }
19965
19966 JSON_THROW(std::out_of_range("key not found"));
19967 }
19968
19969 template<class KeyType, detail::enable_if_t<
19970 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19971 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19972 {
19973 for (auto it = this->begin(); it != this->end(); ++it)
19974 {
19975 if (m_compare(it->first, key))
19976 {
19977 return it->second;
19978 }
19979 }
19980
19981 JSON_THROW(std::out_of_range("key not found"));
19982 }
19983
19984 size_type erase(const key_type& key)
19985 {
19986 for (auto it = this->begin(); it != this->end(); ++it)
19987 {
19988 if (m_compare(it->first, key))
19989 {
19990 // Since we cannot move const Keys, re-construct them in place
19991 for (auto next = it; ++next != this->end(); ++it)
19992 {
19993 it->~value_type(); // Destroy but keep allocation
19994 new (&*it) value_type{std::move(*next)};
19995 }
19996 Container::pop_back();
19997 return 1;
19998 }
19999 }
20000 return 0;
20001 }
20002
20003 template<class KeyType, detail::enable_if_t<
20004 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20005 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20006 {
20007 for (auto it = this->begin(); it != this->end(); ++it)
20008 {
20009 if (m_compare(it->first, key))
20010 {
20011 // Since we cannot move const Keys, re-construct them in place
20012 for (auto next = it; ++next != this->end(); ++it)
20013 {
20014 it->~value_type(); // Destroy but keep allocation
20015 new (&*it) value_type{std::move(*next)};
20016 }
20017 Container::pop_back();
20018 return 1;
20019 }
20020 }
20021 return 0;
20022 }
20023
20024 iterator erase(iterator pos)
20025 {
20026 return erase(pos, std::next(pos));
20027 }
20028
20029 iterator erase(iterator first, iterator last)
20030 {
20031 if (first == last)
20032 {
20033 return first;
20034 }
20035
20036 const auto elements_affected = std::distance(first, last);
20037 const auto offset = std::distance(Container::begin(), first);
20038
20039 // This is the start situation. We need to delete elements_affected
20040 // elements (3 in this example: e, f, g), and need to return an
20041 // iterator past the last deleted element (h in this example).
20042 // Note that offset is the distance from the start of the vector
20043 // to first. We will need this later.
20044
20045 // [ a, b, c, d, e, f, g, h, i, j ]
20046 // ^ ^
20047 // first last
20048
20049 // Since we cannot move const Keys, we re-construct them in place.
20050 // We start at first and re-construct (viz. copy) the elements from
20051 // the back of the vector. Example for the first iteration:
20052
20053 // ,--------.
20054 // v | destroy e and re-construct with h
20055 // [ a, b, c, d, e, f, g, h, i, j ]
20056 // ^ ^
20057 // it it + elements_affected
20058
20059 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20060 {
20061 it->~value_type(); // destroy but keep allocation
20062 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20063 }
20064
20065 // [ a, b, c, d, h, i, j, h, i, j ]
20066 // ^ ^
20067 // first last
20068
20069 // remove the unneeded elements at the end of the vector
20070 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20071
20072 // [ a, b, c, d, h, i, j ]
20073 // ^ ^
20074 // first last
20075
20076 // first is now pointing past the last deleted element, but we cannot
20077 // use this iterator, because it may have been invalidated by the
20078 // resize call. Instead, we can return begin() + offset.
20079 return Container::begin() + offset;
20080 }
20081
20082 size_type count(const key_type& key) const
20083 {
20084 for (auto it = this->begin(); it != this->end(); ++it)
20085 {
20086 if (m_compare(it->first, key))
20087 {
20088 return 1;
20089 }
20090 }
20091 return 0;
20092 }
20093
20094 template<class KeyType, detail::enable_if_t<
20095 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20096 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20097 {
20098 for (auto it = this->begin(); it != this->end(); ++it)
20099 {
20100 if (m_compare(it->first, key))
20101 {
20102 return 1;
20103 }
20104 }
20105 return 0;
20106 }
20107
20108 iterator find(const key_type& key)
20109 {
20110 for (auto it = this->begin(); it != this->end(); ++it)
20111 {
20112 if (m_compare(it->first, key))
20113 {
20114 return it;
20115 }
20116 }
20117 return Container::end();
20118 }
20119
20120 template<class KeyType, detail::enable_if_t<
20121 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20122 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20123 {
20124 for (auto it = this->begin(); it != this->end(); ++it)
20125 {
20126 if (m_compare(it->first, key))
20127 {
20128 return it;
20129 }
20130 }
20131 return Container::end();
20132 }
20133
20134 const_iterator find(const key_type& key) const
20135 {
20136 for (auto it = this->begin(); it != this->end(); ++it)
20137 {
20138 if (m_compare(it->first, key))
20139 {
20140 return it;
20141 }
20142 }
20143 return Container::end();
20144 }
20145
20146 std::pair<iterator, bool> insert( value_type&& value )
20147 {
20148 return emplace(value.first, std::move(value.second));
20149 }
20150
20151 std::pair<iterator, bool> insert( const value_type& value )
20152 {
20153 for (auto it = this->begin(); it != this->end(); ++it)
20154 {
20155 if (m_compare(it->first, value.first))
20156 {
20157 return {it, false};
20158 }
20159 }
20160 Container::push_back(value);
20161 return {--this->end(), true};
20162 }
20163
20164 template<typename InputIt>
20165 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20166 std::input_iterator_tag>::value>::type;
20167
20168 template<typename InputIt, typename = require_input_iter<InputIt>>
20169 void insert(InputIt first, InputIt last)
20170 {
20171 for (auto it = first; it != last; ++it)
20172 {
20173 insert(*it);
20174 }
20175 }
20176
20177private:
20178 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20179};
20180
20181NLOHMANN_JSON_NAMESPACE_END
20182
20183
20184#if defined(JSON_HAS_CPP_17)
20185 #if JSON_HAS_STATIC_RTTI
20186 #include <any>
20187 #endif
20188 #include <string_view>
20189#endif
20190
20196NLOHMANN_JSON_NAMESPACE_BEGIN
20197
20216NLOHMANN_BASIC_JSON_TPL_DECLARATION
20217class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20218 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20219{
20220 private:
20221 template<detail::value_t> friend struct detail::external_constructor;
20222
20223 template<typename>
20224 friend class ::nlohmann::json_pointer;
20225 // can be restored when json_pointer backwards compatibility is removed
20226 // friend ::nlohmann::json_pointer<StringType>;
20227
20228 template<typename BasicJsonType, typename InputType>
20229 friend class ::nlohmann::detail::parser;
20230 friend ::nlohmann::detail::serializer<basic_json>;
20231 template<typename BasicJsonType>
20232 friend class ::nlohmann::detail::iter_impl;
20233 template<typename BasicJsonType, typename CharType>
20234 friend class ::nlohmann::detail::binary_writer;
20235 template<typename BasicJsonType, typename InputType, typename SAX>
20236 friend class ::nlohmann::detail::binary_reader;
20237 template<typename BasicJsonType, typename InputAdapterType>
20238 friend class ::nlohmann::detail::json_sax_dom_parser;
20239 template<typename BasicJsonType, typename InputAdapterType>
20240 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20241 friend class ::nlohmann::detail::exception;
20242
20244 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20245 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20246
20247 JSON_PRIVATE_UNLESS_TESTED:
20248 // convenience aliases for types residing in namespace detail;
20249 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20250
20251 template<typename InputAdapterType>
20252 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20253 InputAdapterType adapter,
20254 detail::parser_callback_t<basic_json>cb = nullptr,
20255 const bool allow_exceptions = true,
20256 const bool ignore_comments = false,
20257 const bool ignore_trailing_commas = false
20258 )
20259 {
20260 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20261 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
20262 }
20263
20264 private:
20265 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20266 template<typename BasicJsonType>
20267 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20268 template<typename BasicJsonType>
20269 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20270 template<typename Iterator>
20271 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20272 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20273
20274 template<typename CharType>
20275 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20276
20277 template<typename InputType>
20278 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20279 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20280
20281 JSON_PRIVATE_UNLESS_TESTED:
20282 using serializer = ::nlohmann::detail::serializer<basic_json>;
20283
20284 public:
20285 using value_t = detail::value_t;
20287 using json_pointer = ::nlohmann::json_pointer<StringType>;
20288 template<typename T, typename SFINAE>
20289 using json_serializer = JSONSerializer<T, SFINAE>;
20297 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20298
20299 using input_format_t = detail::input_format_t;
20302
20304 // exceptions //
20306
20310
20311 using exception = detail::exception;
20312 using parse_error = detail::parse_error;
20313 using invalid_iterator = detail::invalid_iterator;
20314 using type_error = detail::type_error;
20315 using out_of_range = detail::out_of_range;
20316 using other_error = detail::other_error;
20317
20319
20321 // container types //
20323
20328
20331
20336
20338 using difference_type = std::ptrdiff_t;
20340 using size_type = std::size_t;
20341
20343 using allocator_type = AllocatorType<basic_json>;
20344
20346 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20348 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20349
20351 using iterator = iter_impl<basic_json>;
20353 using const_iterator = iter_impl<const basic_json>;
20355 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20357 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20358
20360
20364 {
20365 return allocator_type();
20366 }
20367
20370 JSON_HEDLEY_WARN_UNUSED_RESULT
20372 {
20373 basic_json result;
20374
20375 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20376 result["name"] = "JSON for Modern C++";
20377 result["url"] = "https://github.com/nlohmann/json";
20378 result["version"]["string"] =
20379 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20380 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20381 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20382 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20383 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20384 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20385
20386#ifdef _WIN32
20387 result["platform"] = "win32";
20388#elif defined __linux__
20389 result["platform"] = "linux";
20390#elif defined __APPLE__
20391 result["platform"] = "apple";
20392#elif defined __unix__
20393 result["platform"] = "unix";
20394#else
20395 result["platform"] = "unknown";
20396#endif
20397
20398#if defined(__ICC) || defined(__INTEL_COMPILER)
20399 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20400#elif defined(__clang__)
20401 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20402#elif defined(__GNUC__) || defined(__GNUG__)
20403 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20404 std::to_string(__GNUC__), '.',
20405 std::to_string(__GNUC_MINOR__), '.',
20406 std::to_string(__GNUC_PATCHLEVEL__))
20407 }
20408 };
20409#elif defined(__HP_cc) || defined(__HP_aCC)
20410 result["compiler"] = "hp"
20411#elif defined(__IBMCPP__)
20412 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20413#elif defined(_MSC_VER)
20414 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20415#elif defined(__PGI)
20416 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20417#elif defined(__SUNPRO_CC)
20418 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20419#else
20420 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20421#endif
20422
20423#if defined(_MSVC_LANG)
20424 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20425#elif defined(__cplusplus)
20426 result["compiler"]["c++"] = std::to_string(__cplusplus);
20427#else
20428 result["compiler"]["c++"] = "unknown";
20429#endif
20430 return result;
20431 }
20432
20434 // JSON value data types //
20436
20441
20446#if defined(JSON_HAS_CPP_14)
20447 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20448 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20449 using default_object_comparator_t = std::less<>;
20450#else
20451 using default_object_comparator_t = std::less<StringType>;
20452#endif
20453
20456 using object_t = ObjectType<StringType,
20457 basic_json,
20459 AllocatorType<std::pair<const StringType,
20460 basic_json>>>;
20461
20464 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20465
20468 using string_t = StringType;
20469
20472 using boolean_t = BooleanType;
20473
20476 using number_integer_t = NumberIntegerType;
20477
20480 using number_unsigned_t = NumberUnsignedType;
20481
20484 using number_float_t = NumberFloatType;
20485
20488 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20489
20492 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
20493
20495
20496 private:
20497
20499 template<typename T, typename... Args>
20500 JSON_HEDLEY_RETURNS_NON_NULL
20501 static T* create(Args&& ... args)
20502 {
20503 AllocatorType<T> alloc;
20504 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20505
20506 auto deleter = [&](T * obj)
20507 {
20508 AllocatorTraits::deallocate(alloc, obj, 1);
20509 };
20510 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20511 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20512 JSON_ASSERT(obj != nullptr);
20513 return obj.release();
20514 }
20515
20517 // JSON value storage //
20519
20520 JSON_PRIVATE_UNLESS_TESTED:
20546 union json_value
20547 {
20549 object_t* object;
20551 array_t* array;
20553 string_t* string;
20555 binary_t* binary;
20557 boolean_t boolean;
20559 number_integer_t number_integer;
20561 number_unsigned_t number_unsigned;
20563 number_float_t number_float;
20564
20566 json_value() = default;
20568 json_value(boolean_t v) noexcept : boolean(v) {}
20570 json_value(number_integer_t v) noexcept : number_integer(v) {}
20572 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20574 json_value(number_float_t v) noexcept : number_float(v) {}
20576 json_value(value_t t)
20577 {
20578 switch (t)
20579 {
20580 case value_t::object:
20581 {
20582 object = create<object_t>();
20583 break;
20584 }
20585
20586 case value_t::array:
20587 {
20588 array = create<array_t>();
20589 break;
20590 }
20591
20592 case value_t::string:
20593 {
20594 string = create<string_t>("");
20595 break;
20596 }
20597
20598 case value_t::binary:
20599 {
20600 binary = create<binary_t>();
20601 break;
20602 }
20603
20604 case value_t::boolean:
20605 {
20606 boolean = static_cast<boolean_t>(false);
20607 break;
20608 }
20609
20610 case value_t::number_integer:
20611 {
20612 number_integer = static_cast<number_integer_t>(0);
20613 break;
20614 }
20615
20616 case value_t::number_unsigned:
20617 {
20618 number_unsigned = static_cast<number_unsigned_t>(0);
20619 break;
20620 }
20621
20622 case value_t::number_float:
20623 {
20624 number_float = static_cast<number_float_t>(0.0);
20625 break;
20626 }
20627
20628 case value_t::null:
20629 {
20630 object = nullptr; // silence warning, see #821
20631 break;
20632 }
20633
20634 case value_t::discarded:
20635 default:
20636 {
20637 object = nullptr; // silence warning, see #821
20638 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20639 {
20640 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20641 }
20642 break;
20643 }
20644 }
20645 }
20646
20648 json_value(const string_t& value) : string(create<string_t>(value)) {}
20649
20651 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20652
20654 json_value(const object_t& value) : object(create<object_t>(value)) {}
20655
20657 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20658
20660 json_value(const array_t& value) : array(create<array_t>(value)) {}
20661
20663 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20664
20666 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20667
20669 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20670
20672 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20673
20675 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20676
20677 void destroy(value_t t)
20678 {
20679 if (
20680 (t == value_t::object && object == nullptr) ||
20681 (t == value_t::array && array == nullptr) ||
20682 (t == value_t::string && string == nullptr) ||
20683 (t == value_t::binary && binary == nullptr)
20684 )
20685 {
20686 // not initialized (e.g., due to exception in the ctor)
20687 return;
20688 }
20689 if (t == value_t::array || t == value_t::object)
20690 {
20691 // flatten the current json_value to a heap-allocated stack
20692 std::vector<basic_json> stack;
20693
20694 // move the top-level items to stack
20695 if (t == value_t::array)
20696 {
20697 stack.reserve(array->size());
20698 std::move(array->begin(), array->end(), std::back_inserter(stack));
20699 }
20700 else
20701 {
20702 stack.reserve(object->size());
20703 for (auto&& it : *object)
20704 {
20705 stack.push_back(std::move(it.second));
20706 }
20707 }
20708
20709 while (!stack.empty())
20710 {
20711 // move the last item to a local variable to be processed
20712 basic_json current_item(std::move(stack.back()));
20713 stack.pop_back();
20714
20715 // if current_item is array/object, move
20716 // its children to the stack to be processed later
20717 if (current_item.is_array())
20718 {
20719 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20720
20721 current_item.m_data.m_value.array->clear();
20722 }
20723 else if (current_item.is_object())
20724 {
20725 for (auto&& it : *current_item.m_data.m_value.object)
20726 {
20727 stack.push_back(std::move(it.second));
20728 }
20729
20730 current_item.m_data.m_value.object->clear();
20731 }
20732
20733 // it's now safe that current_item gets destructed
20734 // since it doesn't have any children
20735 }
20736 }
20737
20738 switch (t)
20739 {
20740 case value_t::object:
20741 {
20742 AllocatorType<object_t> alloc;
20743 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20744 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20745 break;
20746 }
20747
20748 case value_t::array:
20749 {
20750 AllocatorType<array_t> alloc;
20751 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20752 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20753 break;
20754 }
20755
20756 case value_t::string:
20757 {
20758 AllocatorType<string_t> alloc;
20759 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20760 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20761 break;
20762 }
20763
20764 case value_t::binary:
20765 {
20766 AllocatorType<binary_t> alloc;
20767 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20768 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20769 break;
20770 }
20771
20772 case value_t::null:
20773 case value_t::boolean:
20774 case value_t::number_integer:
20775 case value_t::number_unsigned:
20776 case value_t::number_float:
20777 case value_t::discarded:
20778 default:
20779 {
20780 break;
20781 }
20782 }
20783 }
20784 };
20785
20786 private:
20805 void assert_invariant(bool check_parents = true) const noexcept
20806 {
20807 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20808 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20809 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20810 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20811
20812#if JSON_DIAGNOSTICS
20813 JSON_TRY
20814 {
20815 // cppcheck-suppress assertWithSideEffect
20816 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20817 {
20818 return j.m_parent == this;
20819 }));
20820 }
20821 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20822#endif
20823 static_cast<void>(check_parents);
20824 }
20825
20826 void set_parents()
20827 {
20828#if JSON_DIAGNOSTICS
20829 switch (m_data.m_type)
20830 {
20831 case value_t::array:
20832 {
20833 for (auto& element : *m_data.m_value.array)
20834 {
20835 element.m_parent = this;
20836 }
20837 break;
20838 }
20839
20840 case value_t::object:
20841 {
20842 for (auto& element : *m_data.m_value.object)
20843 {
20844 element.second.m_parent = this;
20845 }
20846 break;
20847 }
20848
20849 case value_t::null:
20850 case value_t::string:
20851 case value_t::boolean:
20852 case value_t::number_integer:
20853 case value_t::number_unsigned:
20854 case value_t::number_float:
20855 case value_t::binary:
20856 case value_t::discarded:
20857 default:
20858 break;
20859 }
20860#endif
20861 }
20862
20863 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20864 {
20865#if JSON_DIAGNOSTICS
20866 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20867 {
20868 (it + i)->m_parent = this;
20869 }
20870#else
20871 static_cast<void>(count_set_parents);
20872#endif
20873 return it;
20874 }
20875
20876 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20877 {
20878#if JSON_DIAGNOSTICS
20879 if (old_capacity != detail::unknown_size())
20880 {
20881 // see https://github.com/nlohmann/json/issues/2838
20882 JSON_ASSERT(type() == value_t::array);
20883 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20884 {
20885 // capacity has changed: update all parents
20886 set_parents();
20887 return j;
20888 }
20889 }
20890
20891 // ordered_json uses a vector internally, so pointers could have
20892 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20893#ifdef JSON_HEDLEY_MSVC_VERSION
20894#pragma warning(push )
20895#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20896#endif
20897 if (detail::is_ordered_map<object_t>::value)
20898 {
20899 set_parents();
20900 return j;
20901 }
20902#ifdef JSON_HEDLEY_MSVC_VERSION
20903#pragma warning( pop )
20904#endif
20905
20906 j.m_parent = this;
20907#else
20908 static_cast<void>(j);
20909 static_cast<void>(old_capacity);
20910#endif
20911 return j;
20912 }
20913
20914 public:
20916 // JSON parser callback //
20918
20922
20925 using parser_callback_t = detail::parser_callback_t<basic_json>;
20926
20928 // constructors //
20930
20935
20938 basic_json(const value_t v)
20939 : m_data(v)
20940 {
20941 assert_invariant();
20942 }
20943
20946 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20947 : basic_json(value_t::null)
20948 {
20949 assert_invariant();
20950 }
20951
20954 template < typename CompatibleType,
20955 typename U = detail::uncvref_t<CompatibleType>,
20956 detail::enable_if_t <
20958 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20959 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20960 std::forward<CompatibleType>(val))))
20961 {
20962 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20963 set_parents();
20964 assert_invariant();
20965 }
20966
20969 template < typename BasicJsonType,
20970 detail::enable_if_t <
20971 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20972 basic_json(const BasicJsonType& val)
20973#if JSON_DIAGNOSTIC_POSITIONS
20974 : start_position(val.start_pos()),
20975 end_position(val.end_pos())
20976#endif
20977 {
20978 using other_boolean_t = typename BasicJsonType::boolean_t;
20979 using other_number_float_t = typename BasicJsonType::number_float_t;
20980 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20981 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20982 using other_string_t = typename BasicJsonType::string_t;
20983 using other_object_t = typename BasicJsonType::object_t;
20984 using other_array_t = typename BasicJsonType::array_t;
20985 using other_binary_t = typename BasicJsonType::binary_t;
20986
20987 switch (val.type())
20988 {
20989 case value_t::boolean:
20990 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20991 break;
20992 case value_t::number_float:
20993 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20994 break;
20995 case value_t::number_integer:
20996 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20997 break;
20998 case value_t::number_unsigned:
20999 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
21000 break;
21001 case value_t::string:
21002 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
21003 break;
21004 case value_t::object:
21005 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
21006 break;
21007 case value_t::array:
21008 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
21009 break;
21010 case value_t::binary:
21011 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
21012 break;
21013 case value_t::null:
21014 *this = nullptr;
21015 break;
21016 case value_t::discarded:
21017 m_data.m_type = value_t::discarded;
21018 break;
21019 default: // LCOV_EXCL_LINE
21020 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
21021 }
21022 JSON_ASSERT(m_data.m_type == val.type());
21023
21024 set_parents();
21025 assert_invariant();
21026 }
21027
21031 bool type_deduction = true,
21032 value_t manual_type = value_t::array)
21033 {
21034 // check if each element is an array with two elements whose first
21035 // element is a string
21036 bool is_an_object = std::all_of(init.begin(), init.end(),
21037 [](const detail::json_ref<basic_json>& element_ref)
21038 {
21039 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
21040 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
21041 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
21042 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
21043 });
21044
21045 // adjust type if type deduction is not wanted
21046 if (!type_deduction)
21047 {
21048 // if an array is wanted, do not create an object though possible
21049 if (manual_type == value_t::array)
21050 {
21051 is_an_object = false;
21052 }
21053
21054 // if an object is wanted but impossible, throw an exception
21055 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21056 {
21057 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21058 }
21059 }
21060
21061 if (is_an_object)
21062 {
21063 // the initializer list is a list of pairs -> create an object
21064 m_data.m_type = value_t::object;
21065 m_data.m_value = value_t::object;
21066
21067 for (auto& element_ref : init)
21068 {
21069 auto element = element_ref.moved_or_copied();
21070 m_data.m_value.object->emplace(
21071 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21072 std::move((*element.m_data.m_value.array)[1]));
21073 }
21074 }
21075 else
21076 {
21077 // the initializer list describes an array -> create an array
21078 m_data.m_type = value_t::array;
21079 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21080 }
21081
21082 set_parents();
21083 assert_invariant();
21084 }
21085
21088 JSON_HEDLEY_WARN_UNUSED_RESULT
21089 static basic_json binary(const typename binary_t::container_type& init)
21090 {
21091 auto res = basic_json();
21092 res.m_data.m_type = value_t::binary;
21093 res.m_data.m_value = init;
21094 return res;
21095 }
21096
21099 JSON_HEDLEY_WARN_UNUSED_RESULT
21100 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21101 {
21102 auto res = basic_json();
21103 res.m_data.m_type = value_t::binary;
21104 res.m_data.m_value = binary_t(init, subtype);
21105 return res;
21106 }
21107
21110 JSON_HEDLEY_WARN_UNUSED_RESULT
21111 static basic_json binary(typename binary_t::container_type&& init)
21112 {
21113 auto res = basic_json();
21114 res.m_data.m_type = value_t::binary;
21115 res.m_data.m_value = std::move(init);
21116 return res;
21117 }
21118
21121 JSON_HEDLEY_WARN_UNUSED_RESULT
21122 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21123 {
21124 auto res = basic_json();
21125 res.m_data.m_type = value_t::binary;
21126 res.m_data.m_value = binary_t(std::move(init), subtype);
21127 return res;
21128 }
21129
21132 JSON_HEDLEY_WARN_UNUSED_RESULT
21134 {
21135 return basic_json(init, false, value_t::array);
21136 }
21137
21140 JSON_HEDLEY_WARN_UNUSED_RESULT
21142 {
21143 return basic_json(init, false, value_t::object);
21144 }
21145
21149 m_data{cnt, val}
21150 {
21151 set_parents();
21152 assert_invariant();
21153 }
21154
21157 template < class InputIT, typename std::enable_if <
21158 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21159 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21160 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21161 {
21162 JSON_ASSERT(first.m_object != nullptr);
21163 JSON_ASSERT(last.m_object != nullptr);
21164
21165 // make sure the iterator fits the current value
21166 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21167 {
21168 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21169 }
21170
21171 // copy type from the first iterator
21172 m_data.m_type = first.m_object->m_data.m_type;
21173
21174 // check if the iterator range is complete for primitive values
21175 switch (m_data.m_type)
21176 {
21177 case value_t::boolean:
21178 case value_t::number_float:
21179 case value_t::number_integer:
21180 case value_t::number_unsigned:
21181 case value_t::string:
21182 {
21183 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21184 || !last.m_it.primitive_iterator.is_end()))
21185 {
21186 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21187 }
21188 break;
21189 }
21190
21191 case value_t::null:
21192 case value_t::object:
21193 case value_t::array:
21194 case value_t::binary:
21195 case value_t::discarded:
21196 default:
21197 break;
21198 }
21199
21200 switch (m_data.m_type)
21201 {
21202 case value_t::number_integer:
21203 {
21204 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21205 break;
21206 }
21207
21208 case value_t::number_unsigned:
21209 {
21210 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21211 break;
21212 }
21213
21214 case value_t::number_float:
21215 {
21216 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21217 break;
21218 }
21219
21220 case value_t::boolean:
21221 {
21222 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21223 break;
21224 }
21225
21226 case value_t::string:
21227 {
21228 m_data.m_value = *first.m_object->m_data.m_value.string;
21229 break;
21230 }
21231
21232 case value_t::object:
21233 {
21234 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21235 last.m_it.object_iterator);
21236 break;
21237 }
21238
21239 case value_t::array:
21240 {
21241 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21242 last.m_it.array_iterator);
21243 break;
21244 }
21245
21246 case value_t::binary:
21247 {
21248 m_data.m_value = *first.m_object->m_data.m_value.binary;
21249 break;
21250 }
21251
21252 case value_t::null:
21253 case value_t::discarded:
21254 default:
21255 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21256 }
21257
21258 set_parents();
21259 assert_invariant();
21260 }
21261
21263 // other constructors and destructor //
21265
21266 template<typename JsonRef,
21267 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
21268 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21269 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21270
21274 : json_base_class_t(other)
21275#if JSON_DIAGNOSTIC_POSITIONS
21276 , start_position(other.start_position)
21277 , end_position(other.end_position)
21278#endif
21279 {
21280 m_data.m_type = other.m_data.m_type;
21281 // check of passed value is valid
21282 other.assert_invariant();
21283
21284 switch (m_data.m_type)
21285 {
21286 case value_t::object:
21287 {
21288 m_data.m_value = *other.m_data.m_value.object;
21289 break;
21290 }
21291
21292 case value_t::array:
21293 {
21294 m_data.m_value = *other.m_data.m_value.array;
21295 break;
21296 }
21297
21298 case value_t::string:
21299 {
21300 m_data.m_value = *other.m_data.m_value.string;
21301 break;
21302 }
21303
21304 case value_t::boolean:
21305 {
21306 m_data.m_value = other.m_data.m_value.boolean;
21307 break;
21308 }
21309
21310 case value_t::number_integer:
21311 {
21312 m_data.m_value = other.m_data.m_value.number_integer;
21313 break;
21314 }
21315
21316 case value_t::number_unsigned:
21317 {
21318 m_data.m_value = other.m_data.m_value.number_unsigned;
21319 break;
21320 }
21321
21322 case value_t::number_float:
21323 {
21324 m_data.m_value = other.m_data.m_value.number_float;
21325 break;
21326 }
21327
21328 case value_t::binary:
21329 {
21330 m_data.m_value = *other.m_data.m_value.binary;
21331 break;
21332 }
21333
21334 case value_t::null:
21335 case value_t::discarded:
21336 default:
21337 break;
21338 }
21339
21340 set_parents();
21341 assert_invariant();
21342 }
21343
21346 basic_json(basic_json&& other) noexcept
21347 : json_base_class_t(std::forward<json_base_class_t>(other)),
21348 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21349#if JSON_DIAGNOSTIC_POSITIONS
21350 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21351 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21352#endif
21353 {
21354 // check that the passed value is valid
21355 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21356
21357 // invalidate payload
21358 other.m_data.m_type = value_t::null;
21359 other.m_data.m_value = {};
21360
21361#if JSON_DIAGNOSTIC_POSITIONS
21362 other.start_position = std::string::npos;
21363 other.end_position = std::string::npos;
21364#endif
21365
21366 set_parents();
21367 assert_invariant();
21368 }
21369
21372 basic_json& operator=(basic_json other) noexcept ( // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
21373 std::is_nothrow_move_constructible<value_t>::value&&
21374 std::is_nothrow_move_assignable<value_t>::value&&
21375 std::is_nothrow_move_constructible<json_value>::value&&
21376 std::is_nothrow_move_assignable<json_value>::value&&
21377 std::is_nothrow_move_assignable<json_base_class_t>::value
21378 )
21379 {
21380 // check that the passed value is valid
21381 other.assert_invariant();
21382
21383 using std::swap;
21384 swap(m_data.m_type, other.m_data.m_type);
21385 swap(m_data.m_value, other.m_data.m_value);
21386
21387#if JSON_DIAGNOSTIC_POSITIONS
21388 swap(start_position, other.start_position);
21389 swap(end_position, other.end_position);
21390#endif
21391
21392 json_base_class_t::operator=(std::move(other));
21393
21394 set_parents();
21395 assert_invariant();
21396 return *this;
21397 }
21398
21401 ~basic_json() noexcept
21402 {
21403 assert_invariant(false);
21404 }
21405
21407
21408 public:
21410 // object inspection //
21412
21416
21419 string_t dump(const int indent = -1,
21420 const char indent_char = ' ',
21421 const bool ensure_ascii = false,
21422 const error_handler_t error_handler = error_handler_t::strict) const
21423 {
21424 string_t result;
21425 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21426
21427 if (indent >= 0)
21428 {
21429 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21430 }
21431 else
21432 {
21433 s.dump(*this, false, ensure_ascii, 0);
21434 }
21435
21436 return result;
21437 }
21438
21441 constexpr value_t type() const noexcept
21442 {
21443 return m_data.m_type;
21444 }
21445
21448 constexpr bool is_primitive() const noexcept
21449 {
21450 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21451 }
21452
21455 constexpr bool is_structured() const noexcept
21456 {
21457 return is_array() || is_object();
21458 }
21459
21462 constexpr bool is_null() const noexcept
21463 {
21464 return m_data.m_type == value_t::null;
21465 }
21466
21469 constexpr bool is_boolean() const noexcept
21470 {
21471 return m_data.m_type == value_t::boolean;
21472 }
21473
21476 constexpr bool is_number() const noexcept
21477 {
21478 return is_number_integer() || is_number_float();
21479 }
21480
21483 constexpr bool is_number_integer() const noexcept
21484 {
21485 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21486 }
21487
21490 constexpr bool is_number_unsigned() const noexcept
21491 {
21492 return m_data.m_type == value_t::number_unsigned;
21493 }
21494
21497 constexpr bool is_number_float() const noexcept
21498 {
21499 return m_data.m_type == value_t::number_float;
21500 }
21501
21504 constexpr bool is_object() const noexcept
21505 {
21506 return m_data.m_type == value_t::object;
21507 }
21508
21511 constexpr bool is_array() const noexcept
21512 {
21513 return m_data.m_type == value_t::array;
21514 }
21515
21518 constexpr bool is_string() const noexcept
21519 {
21520 return m_data.m_type == value_t::string;
21521 }
21522
21525 constexpr bool is_binary() const noexcept
21526 {
21527 return m_data.m_type == value_t::binary;
21528 }
21529
21532 constexpr bool is_discarded() const noexcept
21533 {
21534 return m_data.m_type == value_t::discarded;
21535 }
21536
21539 constexpr operator value_t() const noexcept
21540 {
21541 return m_data.m_type;
21542 }
21543
21545
21546 private:
21548 // value access //
21550
21552 boolean_t get_impl(boolean_t* /*unused*/) const
21553 {
21554 if (JSON_HEDLEY_LIKELY(is_boolean()))
21555 {
21556 return m_data.m_value.boolean;
21557 }
21558
21559 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21560 }
21561
21563 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21564 {
21565 return is_object() ? m_data.m_value.object : nullptr;
21566 }
21567
21569 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21570 {
21571 return is_object() ? m_data.m_value.object : nullptr;
21572 }
21573
21575 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21576 {
21577 return is_array() ? m_data.m_value.array : nullptr;
21578 }
21579
21581 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21582 {
21583 return is_array() ? m_data.m_value.array : nullptr;
21584 }
21585
21587 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21588 {
21589 return is_string() ? m_data.m_value.string : nullptr;
21590 }
21591
21593 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21594 {
21595 return is_string() ? m_data.m_value.string : nullptr;
21596 }
21597
21599 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21600 {
21601 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21602 }
21603
21605 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21606 {
21607 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21608 }
21609
21611 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21612 {
21613 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21614 }
21615
21617 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21618 {
21619 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21620 }
21621
21623 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21624 {
21625 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21626 }
21627
21629 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21630 {
21631 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21632 }
21633
21635 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21636 {
21637 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21638 }
21639
21641 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21642 {
21643 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21644 }
21645
21647 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21648 {
21649 return is_binary() ? m_data.m_value.binary : nullptr;
21650 }
21651
21653 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21654 {
21655 return is_binary() ? m_data.m_value.binary : nullptr;
21656 }
21657
21669 template<typename ReferenceType, typename ThisType>
21670 static ReferenceType get_ref_impl(ThisType& obj)
21671 {
21672 // delegate the call to get_ptr<>()
21673 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21674
21675 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21676 {
21677 return *ptr;
21678 }
21679
21680 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21681 }
21682
21683 public:
21687
21690 template<typename PointerType, typename std::enable_if<
21691 std::is_pointer<PointerType>::value, int>::type = 0>
21692 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21693 {
21694 // delegate the call to get_impl_ptr<>()
21695 return get_impl_ptr(static_cast<PointerType>(nullptr));
21696 }
21697
21700 template < typename PointerType, typename std::enable_if <
21701 std::is_pointer<PointerType>::value&&
21702 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21703 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21704 {
21705 // delegate the call to get_impl_ptr<>() const
21706 return get_impl_ptr(static_cast<PointerType>(nullptr));
21707 }
21708
21709 private:
21748 template < typename ValueType,
21749 detail::enable_if_t <
21752 int > = 0 >
21753 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21754 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21755 {
21756 auto ret = ValueType();
21757 JSONSerializer<ValueType>::from_json(*this, ret);
21758 return ret;
21759 }
21760
21791 template < typename ValueType,
21792 detail::enable_if_t <
21793 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21794 int > = 0 >
21795 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21796 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21797 {
21798 return JSONSerializer<ValueType>::from_json(*this);
21799 }
21800
21816 template < typename BasicJsonType,
21817 detail::enable_if_t <
21818 detail::is_basic_json<BasicJsonType>::value,
21819 int > = 0 >
21820 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21821 {
21822 return *this;
21823 }
21824
21839 template<typename BasicJsonType,
21840 detail::enable_if_t<
21841 std::is_same<BasicJsonType, basic_json_t>::value,
21842 int> = 0>
21843 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21844 {
21845 return *this;
21846 }
21847
21852 template<typename PointerType,
21853 detail::enable_if_t<
21854 std::is_pointer<PointerType>::value,
21855 int> = 0>
21856 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21857 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21858 {
21859 // delegate the call to get_ptr
21860 return get_ptr<PointerType>();
21861 }
21862
21863 public:
21887 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21888#if defined(JSON_HAS_CPP_14)
21889 constexpr
21890#endif
21891 auto get() const noexcept(
21892 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21893 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21894 {
21895 // we cannot static_assert on ValueTypeCV being non-const, because
21896 // there is support for get<const basic_json_t>(), which is why we
21897 // still need the uncvref
21898 static_assert(!std::is_reference<ValueTypeCV>::value,
21899 "get() cannot be used with reference types, you might want to use get_ref()");
21900 return get_impl<ValueType>(detail::priority_tag<4> {});
21901 }
21902
21930 template<typename PointerType, typename std::enable_if<
21931 std::is_pointer<PointerType>::value, int>::type = 0>
21932 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21933 {
21934 // delegate the call to get_ptr
21935 return get_ptr<PointerType>();
21936 }
21937
21940 template < typename ValueType,
21941 detail::enable_if_t <
21944 int > = 0 >
21945 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21946 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21947 {
21948 JSONSerializer<ValueType>::from_json(*this, v);
21949 return v;
21950 }
21951
21952 // specialization to allow calling get_to with a basic_json value
21953 // see https://github.com/nlohmann/json/issues/2175
21954 template<typename ValueType,
21955 detail::enable_if_t <
21957 int> = 0>
21958 ValueType & get_to(ValueType& v) const
21959 {
21960 v = *this;
21961 return v;
21962 }
21963
21964 template <
21965 typename T, std::size_t N,
21966 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21967 detail::enable_if_t <
21968 detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21969 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21970 noexcept(noexcept(JSONSerializer<Array>::from_json(
21971 std::declval<const basic_json_t&>(), v)))
21972 {
21973 JSONSerializer<Array>::from_json(*this, v);
21974 return v;
21975 }
21976
21979 template<typename ReferenceType, typename std::enable_if<
21980 std::is_reference<ReferenceType>::value, int>::type = 0>
21981 ReferenceType get_ref()
21982 {
21983 // delegate call to get_ref_impl
21984 return get_ref_impl<ReferenceType>(*this);
21985 }
21986
21989 template < typename ReferenceType, typename std::enable_if <
21990 std::is_reference<ReferenceType>::value&&
21991 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21992 ReferenceType get_ref() const
21993 {
21994 // delegate call to get_ref_impl
21995 return get_ref_impl<ReferenceType>(*this);
21996 }
21997
22027 template < typename ValueType, typename std::enable_if <
22035#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
22037#endif
22038#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
22040#endif
22042 >::value, int >::type = 0 >
22043 JSON_EXPLICIT operator ValueType() const
22044 {
22045 // delegate the call to get<>() const
22046 return get<ValueType>();
22047 }
22048
22052 {
22053 if (!is_binary())
22054 {
22055 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22056 }
22057
22058 return *get_ptr<binary_t*>();
22059 }
22060
22063 const binary_t& get_binary() const
22064 {
22065 if (!is_binary())
22066 {
22067 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22068 }
22069
22070 return *get_ptr<const binary_t*>();
22071 }
22072
22074
22076 // element access //
22078
22082
22086 {
22087 // at only works for arrays
22088 if (JSON_HEDLEY_LIKELY(is_array()))
22089 {
22090 JSON_TRY
22091 {
22092 return set_parent(m_data.m_value.array->at(idx));
22093 }
22094 JSON_CATCH (std::out_of_range&)
22095 {
22096 // create a better exception explanation
22097 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22098 } // cppcheck-suppress[missingReturn]
22099 }
22100 else
22101 {
22102 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22103 }
22104 }
22105
22109 {
22110 // at only works for arrays
22111 if (JSON_HEDLEY_LIKELY(is_array()))
22112 {
22113 JSON_TRY
22114 {
22115 return m_data.m_value.array->at(idx);
22116 }
22117 JSON_CATCH (std::out_of_range&)
22118 {
22119 // create a better exception explanation
22120 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22121 } // cppcheck-suppress[missingReturn]
22122 }
22123 else
22124 {
22125 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22126 }
22127 }
22128
22131 reference at(const typename object_t::key_type& key)
22132 {
22133 // at only works for objects
22134 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22135 {
22136 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22137 }
22138
22139 auto it = m_data.m_value.object->find(key);
22140 if (it == m_data.m_value.object->end())
22141 {
22142 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22143 }
22144 return set_parent(it->second);
22145 }
22146
22149 template<class KeyType, detail::enable_if_t<
22150 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22151 reference at(KeyType && key)
22152 {
22153 // at only works for objects
22154 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22155 {
22156 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22157 }
22158
22159 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22160 if (it == m_data.m_value.object->end())
22161 {
22162 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22163 }
22164 return set_parent(it->second);
22165 }
22166
22169 const_reference at(const typename object_t::key_type& key) const
22170 {
22171 // at only works for objects
22172 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22173 {
22174 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22175 }
22176
22177 auto it = m_data.m_value.object->find(key);
22178 if (it == m_data.m_value.object->end())
22179 {
22180 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22181 }
22182 return it->second;
22183 }
22184
22187 template<class KeyType, detail::enable_if_t<
22188 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22189 const_reference at(KeyType && key) const
22190 {
22191 // at only works for objects
22192 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22193 {
22194 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22195 }
22196
22197 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22198 if (it == m_data.m_value.object->end())
22199 {
22200 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22201 }
22202 return it->second;
22203 }
22204
22208 {
22209 // implicitly convert a null value to an empty array
22210 if (is_null())
22211 {
22212 m_data.m_type = value_t::array;
22213 m_data.m_value.array = create<array_t>();
22214 assert_invariant();
22215 }
22216
22217 // operator[] only works for arrays
22218 if (JSON_HEDLEY_LIKELY(is_array()))
22219 {
22220 // fill up the array with null values if given idx is outside the range
22221 if (idx >= m_data.m_value.array->size())
22222 {
22223#if JSON_DIAGNOSTICS
22224 // remember array size & capacity before resizing
22225 const auto old_size = m_data.m_value.array->size();
22226 const auto old_capacity = m_data.m_value.array->capacity();
22227#endif
22228 m_data.m_value.array->resize(idx + 1);
22229
22230#if JSON_DIAGNOSTICS
22231 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22232 {
22233 // capacity has changed: update all parents
22234 set_parents();
22235 }
22236 else
22237 {
22238 // set parent for values added above
22239 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22240 }
22241#endif
22242 assert_invariant();
22243 }
22244
22245 return m_data.m_value.array->operator[](idx);
22246 }
22247
22248 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22249 }
22250
22254 {
22255 // const operator[] only works for arrays
22256 if (JSON_HEDLEY_LIKELY(is_array()))
22257 {
22258 return m_data.m_value.array->operator[](idx);
22259 }
22260
22261 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22262 }
22263
22266 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22267 {
22268 // implicitly convert a null value to an empty object
22269 if (is_null())
22270 {
22271 m_data.m_type = value_t::object;
22272 m_data.m_value.object = create<object_t>();
22273 assert_invariant();
22274 }
22275
22276 // operator[] only works for objects
22277 if (JSON_HEDLEY_LIKELY(is_object()))
22278 {
22279 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22280 return set_parent(result.first->second);
22281 }
22282
22283 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22284 }
22285
22288 const_reference operator[](const typename object_t::key_type& key) const
22289 {
22290 // const operator[] only works for objects
22291 if (JSON_HEDLEY_LIKELY(is_object()))
22292 {
22293 auto it = m_data.m_value.object->find(key);
22294 JSON_ASSERT(it != m_data.m_value.object->end());
22295 return it->second;
22296 }
22297
22298 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22299 }
22300
22301 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22302 // (they seemingly cannot be constrained to resolve the ambiguity)
22303 template<typename T>
22304 reference operator[](T* key)
22305 {
22306 return operator[](typename object_t::key_type(key));
22307 }
22308
22309 template<typename T>
22310 const_reference operator[](T* key) const
22311 {
22312 return operator[](typename object_t::key_type(key));
22313 }
22314
22317 template<class KeyType, detail::enable_if_t<
22318 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22320 {
22321 // implicitly convert a null value to an empty object
22322 if (is_null())
22323 {
22324 m_data.m_type = value_t::object;
22325 m_data.m_value.object = create<object_t>();
22326 assert_invariant();
22327 }
22328
22329 // operator[] only works for objects
22330 if (JSON_HEDLEY_LIKELY(is_object()))
22331 {
22332 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22333 return set_parent(result.first->second);
22334 }
22335
22336 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22337 }
22338
22341 template<class KeyType, detail::enable_if_t<
22342 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22344 {
22345 // const operator[] only works for objects
22346 if (JSON_HEDLEY_LIKELY(is_object()))
22347 {
22348 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22349 JSON_ASSERT(it != m_data.m_value.object->end());
22350 return it->second;
22351 }
22352
22353 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22354 }
22355
22356 private:
22357 template<typename KeyType>
22358 using is_comparable_with_object_key = detail::is_comparable <
22359 object_comparator_t, const typename object_t::key_type&, KeyType >;
22360
22361 template<typename ValueType>
22362 using value_return_type = std::conditional <
22363 detail::is_c_string_uncvref<ValueType>::value,
22364 string_t, typename std::decay<ValueType>::type >;
22365
22366 public:
22369 template < class ValueType, detail::enable_if_t <
22371 && detail::is_getable<basic_json_t, ValueType>::value
22372 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22373 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22374 {
22375 // value only works for objects
22376 if (JSON_HEDLEY_LIKELY(is_object()))
22377 {
22378 // If 'key' is found, return its value. Otherwise, return `default_value'.
22379 const auto it = find(key);
22380 if (it != end())
22381 {
22382 return it->template get<ValueType>();
22383 }
22384
22385 return default_value;
22386 }
22387
22388 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22389 }
22390
22393 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22394 detail::enable_if_t <
22396 && detail::is_getable<basic_json_t, ReturnType>::value
22397 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22398 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22399 {
22400 // value only works for objects
22401 if (JSON_HEDLEY_LIKELY(is_object()))
22402 {
22403 // If 'key' is found, return its value. Otherwise, return `default_value'.
22404 const auto it = find(key);
22405 if (it != end())
22406 {
22407 return it->template get<ReturnType>();
22408 }
22409
22410 return std::forward<ValueType>(default_value);
22411 }
22412
22413 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22414 }
22415
22418 template < class ValueType, class KeyType, detail::enable_if_t <
22420 && !detail::is_json_pointer<KeyType>::value
22421 && is_comparable_with_object_key<KeyType>::value
22422 && detail::is_getable<basic_json_t, ValueType>::value
22423 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22424 ValueType value(KeyType && key, const ValueType& default_value) const
22425 {
22426 // value only works for objects
22427 if (JSON_HEDLEY_LIKELY(is_object()))
22428 {
22429 // If 'key' is found, return its value. Otherwise, return `default_value'.
22430 const auto it = find(std::forward<KeyType>(key));
22431 if (it != end())
22432 {
22433 return it->template get<ValueType>();
22434 }
22435
22436 return default_value;
22437 }
22438
22439 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22440 }
22441
22444 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22445 detail::enable_if_t <
22447 && !detail::is_json_pointer<KeyType>::value
22448 && is_comparable_with_object_key<KeyType>::value
22449 && detail::is_getable<basic_json_t, ReturnType>::value
22450 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22451 ReturnType value(KeyType && key, ValueType && default_value) const
22452 {
22453 // value only works for objects
22454 if (JSON_HEDLEY_LIKELY(is_object()))
22455 {
22456 // If 'key' is found, return its value. Otherwise, return `default_value'.
22457 const auto it = find(std::forward<KeyType>(key));
22458 if (it != end())
22459 {
22460 return it->template get<ReturnType>();
22461 }
22462
22463 return std::forward<ValueType>(default_value);
22464 }
22465
22466 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22467 }
22468
22471 template < class ValueType, detail::enable_if_t <
22472 detail::is_getable<basic_json_t, ValueType>::value
22473 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22474 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22475 {
22476 // value only works for objects
22477 if (JSON_HEDLEY_LIKELY(is_object()))
22478 {
22479 // If the pointer resolves to a value, return it. Otherwise, return
22480 // 'default_value'.
22481 JSON_TRY
22482 {
22483 return ptr.get_checked(this).template get<ValueType>();
22484 }
22485 JSON_INTERNAL_CATCH (out_of_range&)
22486 {
22487 return default_value;
22488 }
22489 }
22490
22491 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22492 }
22493
22496 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22497 detail::enable_if_t <
22498 detail::is_getable<basic_json_t, ReturnType>::value
22499 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22500 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22501 {
22502 // value only works for objects
22503 if (JSON_HEDLEY_LIKELY(is_object()))
22504 {
22505 // If the pointer resolves to a value, return it. Otherwise, return
22506 // 'default_value'.
22507 JSON_TRY
22508 {
22509 return ptr.get_checked(this).template get<ReturnType>();
22510 }
22511 JSON_INTERNAL_CATCH (out_of_range&)
22512 {
22513 return std::forward<ValueType>(default_value);
22514 }
22515 }
22516
22517 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22518 }
22519
22520 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22522 && detail::is_getable<basic_json_t, ValueType>::value
22523 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22524 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22525 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22526 {
22527 return value(ptr.convert(), default_value);
22528 }
22529
22530 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22531 detail::enable_if_t <
22532 detail::is_basic_json<BasicJsonType>::value
22533 && detail::is_getable<basic_json_t, ReturnType>::value
22534 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22535 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22536 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22537 {
22538 return value(ptr.convert(), std::forward<ValueType>(default_value));
22539 }
22540
22544 {
22545 return *begin();
22546 }
22547
22551 {
22552 return *cbegin();
22553 }
22554
22558 {
22559 auto tmp = end();
22560 --tmp;
22561 return *tmp;
22562 }
22563
22567 {
22568 auto tmp = cend();
22569 --tmp;
22570 return *tmp;
22571 }
22572
22575 template < class IteratorType, detail::enable_if_t <
22576 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22577 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22578 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22579 {
22580 // make sure the iterator fits the current value
22581 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22582 {
22583 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22584 }
22585
22586 IteratorType result = end();
22587
22588 switch (m_data.m_type)
22589 {
22590 case value_t::boolean:
22591 case value_t::number_float:
22592 case value_t::number_integer:
22593 case value_t::number_unsigned:
22594 case value_t::string:
22595 case value_t::binary:
22596 {
22597 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22598 {
22599 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22600 }
22601
22602 if (is_string())
22603 {
22604 AllocatorType<string_t> alloc;
22605 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22606 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22607 m_data.m_value.string = nullptr;
22608 }
22609 else if (is_binary())
22610 {
22611 AllocatorType<binary_t> alloc;
22612 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22613 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22614 m_data.m_value.binary = nullptr;
22615 }
22616
22617 m_data.m_type = value_t::null;
22618 assert_invariant();
22619 break;
22620 }
22621
22622 case value_t::object:
22623 {
22624 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22625 break;
22626 }
22627
22628 case value_t::array:
22629 {
22630 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22631 break;
22632 }
22633
22634 case value_t::null:
22635 case value_t::discarded:
22636 default:
22637 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22638 }
22639
22640 return result;
22641 }
22642
22645 template < class IteratorType, detail::enable_if_t <
22646 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22647 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22648 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22649 {
22650 // make sure the iterator fits the current value
22651 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22652 {
22653 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22654 }
22655
22656 IteratorType result = end();
22657
22658 switch (m_data.m_type)
22659 {
22660 case value_t::boolean:
22661 case value_t::number_float:
22662 case value_t::number_integer:
22663 case value_t::number_unsigned:
22664 case value_t::string:
22665 case value_t::binary:
22666 {
22667 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22668 || !last.m_it.primitive_iterator.is_end()))
22669 {
22670 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22671 }
22672
22673 if (is_string())
22674 {
22675 AllocatorType<string_t> alloc;
22676 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22677 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22678 m_data.m_value.string = nullptr;
22679 }
22680 else if (is_binary())
22681 {
22682 AllocatorType<binary_t> alloc;
22683 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22684 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22685 m_data.m_value.binary = nullptr;
22686 }
22687
22688 m_data.m_type = value_t::null;
22689 assert_invariant();
22690 break;
22691 }
22692
22693 case value_t::object:
22694 {
22695 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22696 last.m_it.object_iterator);
22697 break;
22698 }
22699
22700 case value_t::array:
22701 {
22702 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22703 last.m_it.array_iterator);
22704 break;
22705 }
22706
22707 case value_t::null:
22708 case value_t::discarded:
22709 default:
22710 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22711 }
22712
22713 return result;
22714 }
22715
22716 private:
22717 template < typename KeyType, detail::enable_if_t <
22718 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22719 size_type erase_internal(KeyType && key)
22720 {
22721 // this erase only works for objects
22722 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22723 {
22724 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22725 }
22726
22727 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22728 }
22729
22730 template < typename KeyType, detail::enable_if_t <
22731 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22732 size_type erase_internal(KeyType && key)
22733 {
22734 // this erase only works for objects
22735 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22736 {
22737 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22738 }
22739
22740 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22741 if (it != m_data.m_value.object->end())
22742 {
22743 m_data.m_value.object->erase(it);
22744 return 1;
22745 }
22746 return 0;
22747 }
22748
22749 public:
22750
22753 size_type erase(const typename object_t::key_type& key)
22754 {
22755 // the indirection via erase_internal() is added to avoid making this
22756 // function a template and thus de-rank it during overload resolution
22757 return erase_internal(key);
22758 }
22759
22762 template<class KeyType, detail::enable_if_t<
22763 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22764 size_type erase(KeyType && key)
22765 {
22766 return erase_internal(std::forward<KeyType>(key));
22767 }
22768
22771 void erase(const size_type idx)
22772 {
22773 // this erase only works for arrays
22774 if (JSON_HEDLEY_LIKELY(is_array()))
22775 {
22776 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22777 {
22778 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22779 }
22780
22781 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22782 }
22783 else
22784 {
22785 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22786 }
22787 }
22788
22790
22792 // lookup //
22794
22797
22800 iterator find(const typename object_t::key_type& key)
22801 {
22802 auto result = end();
22803
22804 if (is_object())
22805 {
22806 result.m_it.object_iterator = m_data.m_value.object->find(key);
22807 }
22808
22809 return result;
22810 }
22811
22814 const_iterator find(const typename object_t::key_type& key) const
22815 {
22816 auto result = cend();
22817
22818 if (is_object())
22819 {
22820 result.m_it.object_iterator = m_data.m_value.object->find(key);
22821 }
22822
22823 return result;
22824 }
22825
22828 template<class KeyType, detail::enable_if_t<
22829 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22830 iterator find(KeyType && key)
22831 {
22832 auto result = end();
22833
22834 if (is_object())
22835 {
22836 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22837 }
22838
22839 return result;
22840 }
22841
22844 template<class KeyType, detail::enable_if_t<
22845 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22846 const_iterator find(KeyType && key) const
22847 {
22848 auto result = cend();
22849
22850 if (is_object())
22851 {
22852 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22853 }
22854
22855 return result;
22856 }
22857
22860 size_type count(const typename object_t::key_type& key) const
22861 {
22862 // return 0 for all nonobject types
22863 return is_object() ? m_data.m_value.object->count(key) : 0;
22864 }
22865
22868 template<class KeyType, detail::enable_if_t<
22869 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22870 size_type count(KeyType && key) const
22871 {
22872 // return 0 for all nonobject types
22873 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22874 }
22875
22878 bool contains(const typename object_t::key_type& key) const
22879 {
22880 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22881 }
22882
22885 template<class KeyType, detail::enable_if_t<
22886 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22887 bool contains(KeyType && key) const
22888 {
22889 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22890 }
22891
22894 bool contains(const json_pointer& ptr) const
22895 {
22896 return ptr.contains(this);
22897 }
22898
22899 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22900 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22901 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22902 {
22903 return ptr.contains(this);
22904 }
22905
22907
22909 // iterators //
22911
22914
22917 iterator begin() noexcept
22918 {
22919 iterator result(this);
22920 result.set_begin();
22921 return result;
22922 }
22923
22926 const_iterator begin() const noexcept
22927 {
22928 return cbegin();
22929 }
22930
22933 const_iterator cbegin() const noexcept
22934 {
22935 const_iterator result(this);
22936 result.set_begin();
22937 return result;
22938 }
22939
22942 iterator end() noexcept
22943 {
22944 iterator result(this);
22945 result.set_end();
22946 return result;
22947 }
22948
22951 const_iterator end() const noexcept
22952 {
22953 return cend();
22954 }
22955
22958 const_iterator cend() const noexcept
22959 {
22960 const_iterator result(this);
22961 result.set_end();
22962 return result;
22963 }
22964
22968 {
22969 return reverse_iterator(end());
22970 }
22971
22975 {
22976 return crbegin();
22977 }
22978
22982 {
22983 return reverse_iterator(begin());
22984 }
22985
22989 {
22990 return crend();
22991 }
22992
22996 {
22997 return const_reverse_iterator(cend());
22998 }
22999
23003 {
23005 }
23006
23007 public:
23013 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23014 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
23015 {
23016 return ref.items();
23017 }
23018
23024 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
23025 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
23026 {
23027 return ref.items();
23028 }
23029
23032 iteration_proxy<iterator> items() noexcept
23033 {
23034 return iteration_proxy<iterator>(*this);
23035 }
23036
23039 iteration_proxy<const_iterator> items() const noexcept
23040 {
23041 return iteration_proxy<const_iterator>(*this);
23042 }
23043
23045
23047 // capacity //
23049
23052
23055 bool empty() const noexcept
23056 {
23057 switch (m_data.m_type)
23058 {
23059 case value_t::null:
23060 {
23061 // null values are empty
23062 return true;
23063 }
23064
23065 case value_t::array:
23066 {
23067 // delegate call to array_t::empty()
23068 return m_data.m_value.array->empty();
23069 }
23070
23071 case value_t::object:
23072 {
23073 // delegate call to object_t::empty()
23074 return m_data.m_value.object->empty();
23075 }
23076
23077 case value_t::string:
23078 case value_t::boolean:
23079 case value_t::number_integer:
23080 case value_t::number_unsigned:
23081 case value_t::number_float:
23082 case value_t::binary:
23083 case value_t::discarded:
23084 default:
23085 {
23086 // all other types are nonempty
23087 return false;
23088 }
23089 }
23090 }
23091
23094 size_type size() const noexcept
23095 {
23096 switch (m_data.m_type)
23097 {
23098 case value_t::null:
23099 {
23100 // null values are empty
23101 return 0;
23102 }
23103
23104 case value_t::array:
23105 {
23106 // delegate call to array_t::size()
23107 return m_data.m_value.array->size();
23108 }
23109
23110 case value_t::object:
23111 {
23112 // delegate call to object_t::size()
23113 return m_data.m_value.object->size();
23114 }
23115
23116 case value_t::string:
23117 case value_t::boolean:
23118 case value_t::number_integer:
23119 case value_t::number_unsigned:
23120 case value_t::number_float:
23121 case value_t::binary:
23122 case value_t::discarded:
23123 default:
23124 {
23125 // all other types have size 1
23126 return 1;
23127 }
23128 }
23129 }
23130
23133 size_type max_size() const noexcept
23134 {
23135 switch (m_data.m_type)
23136 {
23137 case value_t::array:
23138 {
23139 // delegate call to array_t::max_size()
23140 return m_data.m_value.array->max_size();
23141 }
23142
23143 case value_t::object:
23144 {
23145 // delegate call to object_t::max_size()
23146 return m_data.m_value.object->max_size();
23147 }
23148
23149 case value_t::null:
23150 case value_t::string:
23151 case value_t::boolean:
23152 case value_t::number_integer:
23153 case value_t::number_unsigned:
23154 case value_t::number_float:
23155 case value_t::binary:
23156 case value_t::discarded:
23157 default:
23158 {
23159 // all other types have max_size() == size()
23160 return size();
23161 }
23162 }
23163 }
23164
23166
23168 // modifiers //
23170
23173
23176 void clear() noexcept
23177 {
23178 switch (m_data.m_type)
23179 {
23180 case value_t::number_integer:
23181 {
23182 m_data.m_value.number_integer = 0;
23183 break;
23184 }
23185
23186 case value_t::number_unsigned:
23187 {
23188 m_data.m_value.number_unsigned = 0;
23189 break;
23190 }
23191
23192 case value_t::number_float:
23193 {
23194 m_data.m_value.number_float = 0.0;
23195 break;
23196 }
23197
23198 case value_t::boolean:
23199 {
23200 m_data.m_value.boolean = false;
23201 break;
23202 }
23203
23204 case value_t::string:
23205 {
23206 m_data.m_value.string->clear();
23207 break;
23208 }
23209
23210 case value_t::binary:
23211 {
23212 m_data.m_value.binary->clear();
23213 break;
23214 }
23215
23216 case value_t::array:
23217 {
23218 m_data.m_value.array->clear();
23219 break;
23220 }
23221
23222 case value_t::object:
23223 {
23224 m_data.m_value.object->clear();
23225 break;
23226 }
23227
23228 case value_t::null:
23229 case value_t::discarded:
23230 default:
23231 break;
23232 }
23233 }
23234
23238 {
23239 // push_back only works for null objects or arrays
23240 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23241 {
23242 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23243 }
23244
23245 // transform a null object into an array
23246 if (is_null())
23247 {
23248 m_data.m_type = value_t::array;
23249 m_data.m_value = value_t::array;
23250 assert_invariant();
23251 }
23252
23253 // add the element to the array (move semantics)
23254 const auto old_capacity = m_data.m_value.array->capacity();
23255 m_data.m_value.array->push_back(std::move(val));
23256 set_parent(m_data.m_value.array->back(), old_capacity);
23257 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23258 }
23259
23263 {
23264 push_back(std::move(val));
23265 return *this;
23266 }
23267
23270 void push_back(const basic_json& val)
23271 {
23272 // push_back only works for null objects or arrays
23273 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23274 {
23275 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23276 }
23277
23278 // transform a null object into an array
23279 if (is_null())
23280 {
23281 m_data.m_type = value_t::array;
23282 m_data.m_value = value_t::array;
23283 assert_invariant();
23284 }
23285
23286 // add the element to the array
23287 const auto old_capacity = m_data.m_value.array->capacity();
23288 m_data.m_value.array->push_back(val);
23289 set_parent(m_data.m_value.array->back(), old_capacity);
23290 }
23291
23295 {
23296 push_back(val);
23297 return *this;
23298 }
23299
23302 void push_back(const typename object_t::value_type& val)
23303 {
23304 // push_back only works for null objects or objects
23305 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23306 {
23307 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23308 }
23309
23310 // transform a null object into an object
23311 if (is_null())
23312 {
23313 m_data.m_type = value_t::object;
23314 m_data.m_value = value_t::object;
23315 assert_invariant();
23316 }
23317
23318 // add the element to the object
23319 auto res = m_data.m_value.object->insert(val);
23320 set_parent(res.first->second);
23321 }
23322
23325 reference operator+=(const typename object_t::value_type& val)
23326 {
23327 push_back(val);
23328 return *this;
23329 }
23330
23334 {
23335 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23336 {
23337 basic_json&& key = init.begin()->moved_or_copied();
23338 push_back(typename object_t::value_type(
23339 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23340 }
23341 else
23342 {
23343 push_back(basic_json(init));
23344 }
23345 }
23346
23350 {
23351 push_back(init);
23352 return *this;
23353 }
23354
23357 template<class... Args>
23358 reference emplace_back(Args&& ... args)
23359 {
23360 // emplace_back only works for null objects or arrays
23361 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23362 {
23363 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23364 }
23365
23366 // transform a null object into an array
23367 if (is_null())
23368 {
23369 m_data.m_type = value_t::array;
23370 m_data.m_value = value_t::array;
23371 assert_invariant();
23372 }
23373
23374 // add the element to the array (perfect forwarding)
23375 const auto old_capacity = m_data.m_value.array->capacity();
23376 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23377 return set_parent(m_data.m_value.array->back(), old_capacity);
23378 }
23379
23382 template<class... Args>
23383 std::pair<iterator, bool> emplace(Args&& ... args)
23384 {
23385 // emplace only works for null objects or arrays
23386 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23387 {
23388 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23389 }
23390
23391 // transform a null object into an object
23392 if (is_null())
23393 {
23394 m_data.m_type = value_t::object;
23395 m_data.m_value = value_t::object;
23396 assert_invariant();
23397 }
23398
23399 // add the element to the array (perfect forwarding)
23400 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23401 set_parent(res.first->second);
23402
23403 // create a result iterator and set iterator to the result of emplace
23404 auto it = begin();
23405 it.m_it.object_iterator = res.first;
23406
23407 // return pair of iterator and boolean
23408 return {it, res.second};
23409 }
23410
23414 template<typename... Args>
23415 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23416 {
23417 iterator result(this);
23418 JSON_ASSERT(m_data.m_value.array != nullptr);
23419
23420 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23421 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23422 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23423
23424 // This could have been written as:
23425 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23426 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23427
23428 set_parents();
23429 return result;
23430 }
23431
23434 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23435 {
23436 // insert only works for arrays
23437 if (JSON_HEDLEY_LIKELY(is_array()))
23438 {
23439 // check if iterator pos fits to this JSON value
23440 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23441 {
23442 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23443 }
23444
23445 // insert to array and return iterator
23446 return insert_iterator(pos, val);
23447 }
23448
23449 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23450 }
23451
23454 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23455 {
23456 return insert(pos, val);
23457 }
23458
23461 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23462 {
23463 // insert only works for arrays
23464 if (JSON_HEDLEY_LIKELY(is_array()))
23465 {
23466 // check if iterator pos fits to this JSON value
23467 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23468 {
23469 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23470 }
23471
23472 // insert to array and return iterator
23473 return insert_iterator(pos, cnt, val);
23474 }
23475
23476 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23477 }
23478
23481 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23482 {
23483 // insert only works for arrays
23484 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23485 {
23486 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23487 }
23488
23489 // check if iterator pos fits to this JSON value
23490 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23491 {
23492 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23493 }
23494
23495 // check if range iterators belong to the same JSON object
23496 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23497 {
23498 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23499 }
23500
23501 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23502 {
23503 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23504 }
23505
23506 // insert to array and return iterator
23507 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23508 }
23509
23512 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23513 {
23514 // insert only works for arrays
23515 if (JSON_HEDLEY_UNLIKELY(!is_array()))
23516 {
23517 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23518 }
23519
23520 // check if iterator pos fits to this JSON value
23521 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23522 {
23523 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23524 }
23525
23526 // insert to array and return iterator
23527 return insert_iterator(pos, ilist.begin(), ilist.end());
23528 }
23529
23532 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23533 {
23534 // insert only works for objects
23535 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23536 {
23537 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23538 }
23539
23540 // check if range iterators belong to the same JSON object
23541 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23542 {
23543 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23544 }
23545
23546 // passed iterators must belong to objects
23547 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23548 {
23549 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23550 }
23551
23552 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23553 set_parents();
23554 }
23555
23558 void update(const_reference j, bool merge_objects = false)
23559 {
23560 update(j.begin(), j.end(), merge_objects);
23561 }
23562
23565 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23566 {
23567 // implicitly convert a null value to an empty object
23568 if (is_null())
23569 {
23570 m_data.m_type = value_t::object;
23571 m_data.m_value.object = create<object_t>();
23572 assert_invariant();
23573 }
23574
23575 if (JSON_HEDLEY_UNLIKELY(!is_object()))
23576 {
23577 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23578 }
23579
23580 // check if range iterators belong to the same JSON object
23581 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23582 {
23583 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23584 }
23585
23586 // passed iterators must belong to objects
23587 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23588 {
23589 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23590 }
23591
23592 for (auto it = first; it != last; ++it)
23593 {
23594 if (merge_objects && it.value().is_object())
23595 {
23596 auto it2 = m_data.m_value.object->find(it.key());
23597 if (it2 != m_data.m_value.object->end())
23598 {
23599 it2->second.update(it.value(), true);
23600 continue;
23601 }
23602 }
23603 m_data.m_value.object->operator[](it.key()) = it.value();
23604#if JSON_DIAGNOSTICS
23605 m_data.m_value.object->operator[](it.key()).m_parent = this;
23606#endif
23607 }
23608 }
23609
23612 void swap(reference other) noexcept (
23613 std::is_nothrow_move_constructible<value_t>::value&&
23614 std::is_nothrow_move_assignable<value_t>::value&&
23615 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23616 std::is_nothrow_move_assignable<json_value>::value
23617 )
23618 {
23619 std::swap(m_data.m_type, other.m_data.m_type);
23620 std::swap(m_data.m_value, other.m_data.m_value);
23621
23622 set_parents();
23623 other.set_parents();
23624 assert_invariant();
23625 }
23626
23629 friend void swap(reference left, reference right) noexcept (
23630 std::is_nothrow_move_constructible<value_t>::value&&
23631 std::is_nothrow_move_assignable<value_t>::value&&
23632 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23633 std::is_nothrow_move_assignable<json_value>::value
23634 )
23635 {
23636 left.swap(right);
23637 }
23638
23641 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23642 {
23643 // swap only works for arrays
23644 if (JSON_HEDLEY_LIKELY(is_array()))
23645 {
23646 using std::swap;
23647 swap(*(m_data.m_value.array), other);
23648 }
23649 else
23650 {
23651 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23652 }
23653 }
23654
23657 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23658 {
23659 // swap only works for objects
23660 if (JSON_HEDLEY_LIKELY(is_object()))
23661 {
23662 using std::swap;
23663 swap(*(m_data.m_value.object), other);
23664 }
23665 else
23666 {
23667 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23668 }
23669 }
23670
23673 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23674 {
23675 // swap only works for strings
23676 if (JSON_HEDLEY_LIKELY(is_string()))
23677 {
23678 using std::swap;
23679 swap(*(m_data.m_value.string), other);
23680 }
23681 else
23682 {
23683 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23684 }
23685 }
23686
23689 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23690 {
23691 // swap only works for strings
23692 if (JSON_HEDLEY_LIKELY(is_binary()))
23693 {
23694 using std::swap;
23695 swap(*(m_data.m_value.binary), other);
23696 }
23697 else
23698 {
23699 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23700 }
23701 }
23702
23705 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23706 {
23707 // swap only works for strings
23708 if (JSON_HEDLEY_LIKELY(is_binary()))
23709 {
23710 using std::swap;
23711 swap(*(m_data.m_value.binary), other);
23712 }
23713 else
23714 {
23715 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23716 }
23717 }
23718
23720
23722 // lexicographical comparison operators //
23724
23727
23728 // note parentheses around operands are necessary; see
23729 // https://github.com/nlohmann/json/issues/1530
23730#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23731 const auto lhs_type = lhs.type(); \
23732 const auto rhs_type = rhs.type(); \
23733 \
23734 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23735 { \
23736 switch (lhs_type) \
23737 { \
23738 case value_t::array: \
23739 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23740 \
23741 case value_t::object: \
23742 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23743 \
23744 case value_t::null: \
23745 return (null_result); \
23746 \
23747 case value_t::string: \
23748 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23749 \
23750 case value_t::boolean: \
23751 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23752 \
23753 case value_t::number_integer: \
23754 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23755 \
23756 case value_t::number_unsigned: \
23757 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23758 \
23759 case value_t::number_float: \
23760 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23761 \
23762 case value_t::binary: \
23763 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23764 \
23765 case value_t::discarded: \
23766 default: \
23767 return (unordered_result); \
23768 } \
23769 } \
23770 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23771 { \
23772 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23773 } \
23774 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23775 { \
23776 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23777 } \
23778 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23779 { \
23780 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23781 } \
23782 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23783 { \
23784 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23785 } \
23786 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23787 { \
23788 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23789 } \
23790 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23791 { \
23792 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23793 } \
23794 else if(compares_unordered(lhs, rhs))\
23795 {\
23796 return (unordered_result);\
23797 }\
23798 \
23799 return (default_result);
23800
23801 JSON_PRIVATE_UNLESS_TESTED:
23802 // returns true if:
23803 // - any operand is NaN and the other operand is of number type
23804 // - any operand is discarded
23805 // in legacy mode, discarded values are considered ordered if
23806 // an operation is computed as an odd number of inverses of others
23807 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23808 {
23809 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23810 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23811 {
23812 return true;
23813 }
23814#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23815 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23816#else
23817 static_cast<void>(inverse);
23818 return lhs.is_discarded() || rhs.is_discarded();
23819#endif
23820 }
23821
23822 private:
23823 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23824 {
23825 return compares_unordered(*this, rhs, inverse);
23826 }
23827
23828 public:
23829#if JSON_HAS_THREE_WAY_COMPARISON
23832 bool operator==(const_reference rhs) const noexcept
23833 {
23834#ifdef __GNUC__
23835#pragma GCC diagnostic push
23836#pragma GCC diagnostic ignored "-Wfloat-equal"
23837#endif
23838 const_reference lhs = *this;
23839 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23840#ifdef __GNUC__
23841#pragma GCC diagnostic pop
23842#endif
23843 }
23844
23847 template<typename ScalarType>
23848 requires std::is_scalar_v<ScalarType>
23849 bool operator==(ScalarType rhs) const noexcept
23850 {
23851 return *this == basic_json(rhs);
23852 }
23853
23856 bool operator!=(const_reference rhs) const noexcept
23857 {
23858 if (compares_unordered(rhs, true))
23859 {
23860 return false;
23861 }
23862 return !operator==(rhs);
23863 }
23864
23867 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23868 {
23869 const_reference lhs = *this;
23870 // default_result is used if we cannot compare values. In that case,
23871 // we compare types.
23872 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23873 std::partial_ordering::equivalent,
23874 std::partial_ordering::unordered,
23875 lhs_type <=> rhs_type) // *NOPAD*
23876 }
23877
23880 template<typename ScalarType>
23881 requires std::is_scalar_v<ScalarType>
23882 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23883 {
23884 return *this <=> basic_json(rhs); // *NOPAD*
23885 }
23886
23887#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23888 // all operators that are computed as an odd number of inverses of others
23889 // need to be overloaded to emulate the legacy comparison behavior
23890
23893 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23894 bool operator<=(const_reference rhs) const noexcept
23895 {
23896 if (compares_unordered(rhs, true))
23897 {
23898 return false;
23899 }
23900 return !(rhs < *this);
23901 }
23902
23905 template<typename ScalarType>
23906 requires std::is_scalar_v<ScalarType>
23907 bool operator<=(ScalarType rhs) const noexcept
23908 {
23909 return *this <= basic_json(rhs);
23910 }
23911
23914 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23915 bool operator>=(const_reference rhs) const noexcept
23916 {
23917 if (compares_unordered(rhs, true))
23918 {
23919 return false;
23920 }
23921 return !(*this < rhs);
23922 }
23923
23926 template<typename ScalarType>
23927 requires std::is_scalar_v<ScalarType>
23928 bool operator>=(ScalarType rhs) const noexcept
23929 {
23930 return *this >= basic_json(rhs);
23931 }
23932#endif
23933#else
23936 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23937 {
23938#ifdef __GNUC__
23939#pragma GCC diagnostic push
23940#pragma GCC diagnostic ignored "-Wfloat-equal"
23941#endif
23942 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23943#ifdef __GNUC__
23944#pragma GCC diagnostic pop
23945#endif
23946 }
23947
23950 template<typename ScalarType, typename std::enable_if<
23951 std::is_scalar<ScalarType>::value, int>::type = 0>
23952 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23953 {
23954 return lhs == basic_json(rhs);
23955 }
23956
23959 template<typename ScalarType, typename std::enable_if<
23960 std::is_scalar<ScalarType>::value, int>::type = 0>
23961 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23962 {
23963 return basic_json(lhs) == rhs;
23964 }
23965
23968 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23969 {
23970 if (compares_unordered(lhs, rhs, true))
23971 {
23972 return false;
23973 }
23974 return !(lhs == rhs);
23975 }
23976
23979 template<typename ScalarType, typename std::enable_if<
23980 std::is_scalar<ScalarType>::value, int>::type = 0>
23981 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23982 {
23983 return lhs != basic_json(rhs);
23984 }
23985
23988 template<typename ScalarType, typename std::enable_if<
23989 std::is_scalar<ScalarType>::value, int>::type = 0>
23990 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23991 {
23992 return basic_json(lhs) != rhs;
23993 }
23994
23997 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23998 {
23999 // default_result is used if we cannot compare values. In that case,
24000 // we compare types. Note we have to call the operator explicitly,
24001 // because MSVC has problems otherwise.
24002 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
24003 }
24004
24007 template<typename ScalarType, typename std::enable_if<
24008 std::is_scalar<ScalarType>::value, int>::type = 0>
24009 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
24010 {
24011 return lhs < basic_json(rhs);
24012 }
24013
24016 template<typename ScalarType, typename std::enable_if<
24017 std::is_scalar<ScalarType>::value, int>::type = 0>
24018 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
24019 {
24020 return basic_json(lhs) < rhs;
24021 }
24022
24025 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
24026 {
24027 if (compares_unordered(lhs, rhs, true))
24028 {
24029 return false;
24030 }
24031 return !(rhs < lhs);
24032 }
24033
24036 template<typename ScalarType, typename std::enable_if<
24037 std::is_scalar<ScalarType>::value, int>::type = 0>
24038 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
24039 {
24040 return lhs <= basic_json(rhs);
24041 }
24042
24045 template<typename ScalarType, typename std::enable_if<
24046 std::is_scalar<ScalarType>::value, int>::type = 0>
24047 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
24048 {
24049 return basic_json(lhs) <= rhs;
24050 }
24051
24054 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24055 {
24056 // double inverse
24057 if (compares_unordered(lhs, rhs))
24058 {
24059 return false;
24060 }
24061 return !(lhs <= rhs);
24062 }
24063
24066 template<typename ScalarType, typename std::enable_if<
24067 std::is_scalar<ScalarType>::value, int>::type = 0>
24068 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24069 {
24070 return lhs > basic_json(rhs);
24071 }
24072
24075 template<typename ScalarType, typename std::enable_if<
24076 std::is_scalar<ScalarType>::value, int>::type = 0>
24077 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24078 {
24079 return basic_json(lhs) > rhs;
24080 }
24081
24084 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24085 {
24086 if (compares_unordered(lhs, rhs, true))
24087 {
24088 return false;
24089 }
24090 return !(lhs < rhs);
24091 }
24092
24095 template<typename ScalarType, typename std::enable_if<
24096 std::is_scalar<ScalarType>::value, int>::type = 0>
24097 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24098 {
24099 return lhs >= basic_json(rhs);
24100 }
24101
24104 template<typename ScalarType, typename std::enable_if<
24105 std::is_scalar<ScalarType>::value, int>::type = 0>
24106 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24107 {
24108 return basic_json(lhs) >= rhs;
24109 }
24110#endif
24111
24112#undef JSON_IMPLEMENT_OPERATOR
24113
24115
24117 // serialization //
24119
24122#ifndef JSON_NO_IO
24125 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24126 {
24127 // read width member and use it as the indentation parameter if nonzero
24128 const bool pretty_print = o.width() > 0;
24129 const auto indentation = pretty_print ? o.width() : 0;
24130
24131 // reset width to 0 for subsequent calls to this stream
24132 o.width(0);
24133
24134 // do the actual serialization
24135 serializer s(detail::output_adapter<char>(o), o.fill());
24136 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24137 return o;
24138 }
24139
24146 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24147 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24148 {
24149 return o << j;
24150 }
24151#endif // JSON_NO_IO
24153
24155 // deserialization //
24157
24160
24163 template<typename InputType>
24164 JSON_HEDLEY_WARN_UNUSED_RESULT
24165 static basic_json parse(InputType&& i,
24166 parser_callback_t cb = nullptr,
24167 const bool allow_exceptions = true,
24168 const bool ignore_comments = false,
24169 const bool ignore_trailing_commas = false)
24170 {
24171 basic_json result;
24172 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24173 return result;
24174 }
24175
24178 template<typename IteratorType>
24179 JSON_HEDLEY_WARN_UNUSED_RESULT
24180 static basic_json parse(IteratorType first,
24181 IteratorType last,
24182 parser_callback_t cb = nullptr,
24183 const bool allow_exceptions = true,
24184 const bool ignore_comments = false,
24185 const bool ignore_trailing_commas = false)
24186 {
24187 basic_json result;
24188 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24189 return result;
24190 }
24191
24192 JSON_HEDLEY_WARN_UNUSED_RESULT
24193 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24194 static basic_json parse(detail::span_input_adapter&& i,
24195 parser_callback_t cb = nullptr,
24196 const bool allow_exceptions = true,
24197 const bool ignore_comments = false,
24198 const bool ignore_trailing_commas = false)
24199 {
24200 basic_json result;
24201 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
24202 return result;
24203 }
24204
24207 template<typename InputType>
24208 static bool accept(InputType&& i,
24209 const bool ignore_comments = false,
24210 const bool ignore_trailing_commas = false)
24211 {
24212 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24213 }
24214
24217 template<typename IteratorType>
24218 static bool accept(IteratorType first, IteratorType last,
24219 const bool ignore_comments = false,
24220 const bool ignore_trailing_commas = false)
24221 {
24222 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24223 }
24224
24225 JSON_HEDLEY_WARN_UNUSED_RESULT
24226 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24227 static bool accept(detail::span_input_adapter&& i,
24228 const bool ignore_comments = false,
24229 const bool ignore_trailing_commas = false)
24230 {
24231 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
24232 }
24233
24236 template <typename InputType, typename SAX>
24237 JSON_HEDLEY_NON_NULL(2)
24238 static bool sax_parse(InputType&& i, SAX* sax,
24239 input_format_t format = input_format_t::json,
24240 const bool strict = true,
24241 const bool ignore_comments = false,
24242 const bool ignore_trailing_commas = false)
24243 {
24244#if defined(__clang__)
24245#pragma clang diagnostic push
24246#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24247#elif defined(__GNUC__)
24248#pragma GCC diagnostic push
24249#pragma GCC diagnostic ignored "-Wnonnull-compare"
24250#endif
24251 if (sax == nullptr)
24252 {
24253 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24254 }
24255#if defined(__clang__)
24256#pragma clang diagnostic pop
24257#elif defined(__GNUC__)
24258#pragma GCC diagnostic pop
24259#endif
24260 auto ia = detail::input_adapter(std::forward<InputType>(i));
24261 return format == input_format_t::json
24262 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24263 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24264 }
24265
24268 template<class IteratorType, class SAX>
24269 JSON_HEDLEY_NON_NULL(3)
24270 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24271 input_format_t format = input_format_t::json,
24272 const bool strict = true,
24273 const bool ignore_comments = false,
24274 const bool ignore_trailing_commas = false)
24275 {
24276#if defined(__clang__)
24277#pragma clang diagnostic push
24278#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24279#elif defined(__GNUC__)
24280#pragma GCC diagnostic push
24281#pragma GCC diagnostic ignored "-Wnonnull-compare"
24282#endif
24283 if (sax == nullptr)
24284 {
24285 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24286 }
24287#if defined(__clang__)
24288#pragma clang diagnostic pop
24289#elif defined(__GNUC__)
24290#pragma GCC diagnostic pop
24291#endif
24292 auto ia = detail::input_adapter(std::move(first), std::move(last));
24293 return format == input_format_t::json
24294 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24295 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24296 }
24297
24303 template <typename SAX>
24304 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24305 JSON_HEDLEY_NON_NULL(2)
24306 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24307 input_format_t format = input_format_t::json,
24308 const bool strict = true,
24309 const bool ignore_comments = false,
24310 const bool ignore_trailing_commas = false)
24311 {
24312#if defined(__clang__)
24313#pragma clang diagnostic push
24314#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
24315#elif defined(__GNUC__)
24316#pragma GCC diagnostic push
24317#pragma GCC diagnostic ignored "-Wnonnull-compare"
24318#endif
24319 if (sax == nullptr)
24320 {
24321 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
24322 }
24323#if defined(__clang__)
24324#pragma clang diagnostic pop
24325#elif defined(__GNUC__)
24326#pragma GCC diagnostic pop
24327#endif
24328 auto ia = i.get();
24329 return format == input_format_t::json
24330 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24331 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
24332 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24333 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24334 }
24335#ifndef JSON_NO_IO
24342 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24343 friend std::istream& operator<<(basic_json& j, std::istream& i)
24344 {
24345 return operator>>(i, j);
24346 }
24347
24350 friend std::istream& operator>>(std::istream& i, basic_json& j)
24351 {
24352 parser(detail::input_adapter(i)).parse(false, j);
24353 return i;
24354 }
24355#endif // JSON_NO_IO
24357
24359 // convenience functions //
24361
24364 JSON_HEDLEY_RETURNS_NON_NULL
24365 const char* type_name() const noexcept
24366 {
24367 switch (m_data.m_type)
24368 {
24369 case value_t::null:
24370 return "null";
24371 case value_t::object:
24372 return "object";
24373 case value_t::array:
24374 return "array";
24375 case value_t::string:
24376 return "string";
24377 case value_t::boolean:
24378 return "boolean";
24379 case value_t::binary:
24380 return "binary";
24381 case value_t::discarded:
24382 return "discarded";
24383 case value_t::number_integer:
24384 case value_t::number_unsigned:
24385 case value_t::number_float:
24386 return "number";
24387 default:
24388 return "invalid";
24389 }
24390 }
24391
24392 JSON_PRIVATE_UNLESS_TESTED:
24394 // member variables //
24396
24397 struct data
24398 {
24400 value_t m_type = value_t::null;
24401
24403 json_value m_value = {};
24404
24405 data(const value_t v)
24406 : m_type(v), m_value(v)
24407 {
24408 }
24409
24410 data(size_type cnt, const basic_json& val)
24411 : m_type(value_t::array)
24412 {
24413 m_value.array = create<array_t>(cnt, val);
24414 }
24415
24416 data() noexcept = default;
24417 data(data&&) noexcept = default;
24418 data(const data&) noexcept = delete;
24419 data& operator=(data&&) noexcept = delete;
24420 data& operator=(const data&) noexcept = delete;
24421
24422 ~data() noexcept
24423 {
24424 m_value.destroy(m_type);
24425 }
24426 };
24427
24428 data m_data = {};
24429
24430#if JSON_DIAGNOSTICS
24432 basic_json* m_parent = nullptr;
24433#endif
24434
24435#if JSON_DIAGNOSTIC_POSITIONS
24437 std::size_t start_position = std::string::npos;
24439 std::size_t end_position = std::string::npos;
24440 public:
24441 constexpr std::size_t start_pos() const noexcept
24442 {
24443 return start_position;
24444 }
24445
24446 constexpr std::size_t end_pos() const noexcept
24447 {
24448 return end_position;
24449 }
24450#endif
24451
24453 // binary serialization/deserialization //
24455
24458
24459 public:
24462 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24463 {
24464 std::vector<std::uint8_t> result;
24465 to_cbor(j, result);
24466 return result;
24467 }
24468
24472 {
24473 binary_writer<std::uint8_t>(o).write_cbor(j);
24474 }
24475
24479 {
24480 binary_writer<char>(o).write_cbor(j);
24481 }
24482
24485 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24486 {
24487 std::vector<std::uint8_t> result;
24488 to_msgpack(j, result);
24489 return result;
24490 }
24491
24495 {
24496 binary_writer<std::uint8_t>(o).write_msgpack(j);
24497 }
24498
24502 {
24503 binary_writer<char>(o).write_msgpack(j);
24504 }
24505
24508 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24509 const bool use_size = false,
24510 const bool use_type = false)
24511 {
24512 std::vector<std::uint8_t> result;
24513 to_ubjson(j, result, use_size, use_type);
24514 return result;
24515 }
24516
24520 const bool use_size = false, const bool use_type = false)
24521 {
24522 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24523 }
24524
24528 const bool use_size = false, const bool use_type = false)
24529 {
24530 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24531 }
24532
24535 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24536 const bool use_size = false,
24537 const bool use_type = false,
24538 const bjdata_version_t version = bjdata_version_t::draft2)
24539 {
24540 std::vector<std::uint8_t> result;
24541 to_bjdata(j, result, use_size, use_type, version);
24542 return result;
24543 }
24544
24548 const bool use_size = false, const bool use_type = false,
24549 const bjdata_version_t version = bjdata_version_t::draft2)
24550 {
24551 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24552 }
24553
24557 const bool use_size = false, const bool use_type = false,
24558 const bjdata_version_t version = bjdata_version_t::draft2)
24559 {
24560 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24561 }
24562
24565 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24566 {
24567 std::vector<std::uint8_t> result;
24568 to_bson(j, result);
24569 return result;
24570 }
24571
24575 {
24576 binary_writer<std::uint8_t>(o).write_bson(j);
24577 }
24578
24582 {
24583 binary_writer<char>(o).write_bson(j);
24584 }
24585
24588 template<typename InputType>
24589 JSON_HEDLEY_WARN_UNUSED_RESULT
24590 static basic_json from_cbor(InputType&& i,
24591 const bool strict = true,
24592 const bool allow_exceptions = true,
24593 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24594 {
24595 basic_json result;
24596 auto ia = detail::input_adapter(std::forward<InputType>(i));
24597 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24598 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]
24599 return res ? result : basic_json(value_t::discarded);
24600 }
24601
24604 template<typename IteratorType>
24605 JSON_HEDLEY_WARN_UNUSED_RESULT
24606 static basic_json from_cbor(IteratorType first, IteratorType last,
24607 const bool strict = true,
24608 const bool allow_exceptions = true,
24609 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24610 {
24611 basic_json result;
24612 auto ia = detail::input_adapter(std::move(first), std::move(last));
24613 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24614 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]
24615 return res ? result : basic_json(value_t::discarded);
24616 }
24617
24618 template<typename T>
24619 JSON_HEDLEY_WARN_UNUSED_RESULT
24620 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24621 static basic_json from_cbor(const T* ptr, std::size_t len,
24622 const bool strict = true,
24623 const bool allow_exceptions = true,
24624 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24625 {
24626 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24627 }
24628
24629 JSON_HEDLEY_WARN_UNUSED_RESULT
24630 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24631 static basic_json from_cbor(detail::span_input_adapter&& i,
24632 const bool strict = true,
24633 const bool allow_exceptions = true,
24634 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24635 {
24636 basic_json result;
24637 auto ia = i.get();
24638 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24639 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24640 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]
24641 return res ? result : basic_json(value_t::discarded);
24642 }
24643
24646 template<typename InputType>
24647 JSON_HEDLEY_WARN_UNUSED_RESULT
24648 static basic_json from_msgpack(InputType&& i,
24649 const bool strict = true,
24650 const bool allow_exceptions = true)
24651 {
24652 basic_json result;
24653 auto ia = detail::input_adapter(std::forward<InputType>(i));
24654 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24655 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]
24656 return res ? result : basic_json(value_t::discarded);
24657 }
24658
24661 template<typename IteratorType>
24662 JSON_HEDLEY_WARN_UNUSED_RESULT
24663 static basic_json from_msgpack(IteratorType first, IteratorType last,
24664 const bool strict = true,
24665 const bool allow_exceptions = true)
24666 {
24667 basic_json result;
24668 auto ia = detail::input_adapter(std::move(first), std::move(last));
24669 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24670 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]
24671 return res ? result : basic_json(value_t::discarded);
24672 }
24673
24674 template<typename T>
24675 JSON_HEDLEY_WARN_UNUSED_RESULT
24676 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24677 static basic_json from_msgpack(const T* ptr, std::size_t len,
24678 const bool strict = true,
24679 const bool allow_exceptions = true)
24680 {
24681 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24682 }
24683
24684 JSON_HEDLEY_WARN_UNUSED_RESULT
24685 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24686 static basic_json from_msgpack(detail::span_input_adapter&& i,
24687 const bool strict = true,
24688 const bool allow_exceptions = true)
24689 {
24690 basic_json result;
24691 auto ia = i.get();
24692 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24693 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24694 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]
24695 return res ? result : basic_json(value_t::discarded);
24696 }
24697
24700 template<typename InputType>
24701 JSON_HEDLEY_WARN_UNUSED_RESULT
24702 static basic_json from_ubjson(InputType&& i,
24703 const bool strict = true,
24704 const bool allow_exceptions = true)
24705 {
24706 basic_json result;
24707 auto ia = detail::input_adapter(std::forward<InputType>(i));
24708 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24709 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]
24710 return res ? result : basic_json(value_t::discarded);
24711 }
24712
24715 template<typename IteratorType>
24716 JSON_HEDLEY_WARN_UNUSED_RESULT
24717 static basic_json from_ubjson(IteratorType first, IteratorType last,
24718 const bool strict = true,
24719 const bool allow_exceptions = true)
24720 {
24721 basic_json result;
24722 auto ia = detail::input_adapter(std::move(first), std::move(last));
24723 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24724 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]
24725 return res ? result : basic_json(value_t::discarded);
24726 }
24727
24728 template<typename T>
24729 JSON_HEDLEY_WARN_UNUSED_RESULT
24730 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24731 static basic_json from_ubjson(const T* ptr, std::size_t len,
24732 const bool strict = true,
24733 const bool allow_exceptions = true)
24734 {
24735 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24736 }
24737
24738 JSON_HEDLEY_WARN_UNUSED_RESULT
24739 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24740 static basic_json from_ubjson(detail::span_input_adapter&& i,
24741 const bool strict = true,
24742 const bool allow_exceptions = true)
24743 {
24744 basic_json result;
24745 auto ia = i.get();
24746 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24747 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24748 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]
24749 return res ? result : basic_json(value_t::discarded);
24750 }
24751
24754 template<typename InputType>
24755 JSON_HEDLEY_WARN_UNUSED_RESULT
24756 static basic_json from_bjdata(InputType&& i,
24757 const bool strict = true,
24758 const bool allow_exceptions = true)
24759 {
24760 basic_json result;
24761 auto ia = detail::input_adapter(std::forward<InputType>(i));
24762 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24763 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]
24764 return res ? result : basic_json(value_t::discarded);
24765 }
24766
24769 template<typename IteratorType>
24770 JSON_HEDLEY_WARN_UNUSED_RESULT
24771 static basic_json from_bjdata(IteratorType first, IteratorType last,
24772 const bool strict = true,
24773 const bool allow_exceptions = true)
24774 {
24775 basic_json result;
24776 auto ia = detail::input_adapter(std::move(first), std::move(last));
24777 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24778 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]
24779 return res ? result : basic_json(value_t::discarded);
24780 }
24781
24784 template<typename InputType>
24785 JSON_HEDLEY_WARN_UNUSED_RESULT
24786 static basic_json from_bson(InputType&& i,
24787 const bool strict = true,
24788 const bool allow_exceptions = true)
24789 {
24790 basic_json result;
24791 auto ia = detail::input_adapter(std::forward<InputType>(i));
24792 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24793 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]
24794 return res ? result : basic_json(value_t::discarded);
24795 }
24796
24799 template<typename IteratorType>
24800 JSON_HEDLEY_WARN_UNUSED_RESULT
24801 static basic_json from_bson(IteratorType first, IteratorType last,
24802 const bool strict = true,
24803 const bool allow_exceptions = true)
24804 {
24805 basic_json result;
24806 auto ia = detail::input_adapter(std::move(first), std::move(last));
24807 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24808 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]
24809 return res ? result : basic_json(value_t::discarded);
24810 }
24811
24812 template<typename T>
24813 JSON_HEDLEY_WARN_UNUSED_RESULT
24814 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24815 static basic_json from_bson(const T* ptr, std::size_t len,
24816 const bool strict = true,
24817 const bool allow_exceptions = true)
24818 {
24819 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24820 }
24821
24822 JSON_HEDLEY_WARN_UNUSED_RESULT
24823 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24824 static basic_json from_bson(detail::span_input_adapter&& i,
24825 const bool strict = true,
24826 const bool allow_exceptions = true)
24827 {
24828 basic_json result;
24829 auto ia = i.get();
24830 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24831 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24832 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]
24833 return res ? result : basic_json(value_t::discarded);
24834 }
24836
24838 // JSON Pointer support //
24840
24843
24847 {
24848 return ptr.get_unchecked(this);
24849 }
24850
24851 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24852 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24853 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24854 {
24855 return ptr.get_unchecked(this);
24856 }
24857
24861 {
24862 return ptr.get_unchecked(this);
24863 }
24864
24865 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24866 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24867 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24868 {
24869 return ptr.get_unchecked(this);
24870 }
24871
24875 {
24876 return ptr.get_checked(this);
24877 }
24878
24879 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24880 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24881 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24882 {
24883 return ptr.get_checked(this);
24884 }
24885
24889 {
24890 return ptr.get_checked(this);
24891 }
24892
24893 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24894 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24895 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24896 {
24897 return ptr.get_checked(this);
24898 }
24899
24903 {
24904 basic_json result(value_t::object);
24905 json_pointer::flatten("", *this, result);
24906 return result;
24907 }
24908
24912 {
24913 return json_pointer::unflatten(*this);
24914 }
24915
24917
24919 // JSON Patch functions //
24921
24924
24927 void patch_inplace(const basic_json& json_patch)
24928 {
24929 basic_json& result = *this;
24930 // the valid JSON Patch operations
24931 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24932
24933 const auto get_op = [](const string_t& op)
24934 {
24935 if (op == "add")
24936 {
24937 return patch_operations::add;
24938 }
24939 if (op == "remove")
24940 {
24941 return patch_operations::remove;
24942 }
24943 if (op == "replace")
24944 {
24945 return patch_operations::replace;
24946 }
24947 if (op == "move")
24948 {
24949 return patch_operations::move;
24950 }
24951 if (op == "copy")
24952 {
24953 return patch_operations::copy;
24954 }
24955 if (op == "test")
24956 {
24957 return patch_operations::test;
24958 }
24959
24960 return patch_operations::invalid;
24961 };
24962
24963 // wrapper for "add" operation; add value at ptr
24964 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24965 {
24966 // adding to the root of the target document means replacing it
24967 if (ptr.empty())
24968 {
24969 result = val;
24970 return;
24971 }
24972
24973 // make sure the top element of the pointer exists
24974 json_pointer const top_pointer = ptr.top();
24975 if (top_pointer != ptr)
24976 {
24977 result.at(top_pointer);
24978 }
24979
24980 // get reference to the parent of the JSON pointer ptr
24981 const auto last_path = ptr.back();
24982 ptr.pop_back();
24983 // parent must exist when performing patch add per RFC6902 specs
24984 basic_json& parent = result.at(ptr);
24985
24986 switch (parent.m_data.m_type)
24987 {
24988 case value_t::null:
24989 case value_t::object:
24990 {
24991 // use operator[] to add value
24992 parent[last_path] = val;
24993 break;
24994 }
24995
24996 case value_t::array:
24997 {
24998 if (last_path == "-")
24999 {
25000 // special case: append to back
25001 parent.push_back(val);
25002 }
25003 else
25004 {
25005 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
25006 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
25007 {
25008 // avoid undefined behavior
25009 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
25010 }
25011
25012 // default case: insert add offset
25013 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
25014 }
25015 break;
25016 }
25017
25018 // if there exists a parent, it cannot be primitive
25019 case value_t::string: // LCOV_EXCL_LINE
25020 case value_t::boolean: // LCOV_EXCL_LINE
25021 case value_t::number_integer: // LCOV_EXCL_LINE
25022 case value_t::number_unsigned: // LCOV_EXCL_LINE
25023 case value_t::number_float: // LCOV_EXCL_LINE
25024 case value_t::binary: // LCOV_EXCL_LINE
25025 case value_t::discarded: // LCOV_EXCL_LINE
25026 default: // LCOV_EXCL_LINE
25027 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
25028 }
25029 };
25030
25031 // wrapper for "remove" operation; remove value at ptr
25032 const auto operation_remove = [this, & result](json_pointer & ptr)
25033 {
25034 // get reference to the parent of the JSON pointer ptr
25035 const auto last_path = ptr.back();
25036 ptr.pop_back();
25037 basic_json& parent = result.at(ptr);
25038
25039 // remove child
25040 if (parent.is_object())
25041 {
25042 // perform range check
25043 auto it = parent.find(last_path);
25044 if (JSON_HEDLEY_LIKELY(it != parent.end()))
25045 {
25046 parent.erase(it);
25047 }
25048 else
25049 {
25050 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
25051 }
25052 }
25053 else if (parent.is_array())
25054 {
25055 // note erase performs range check
25056 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
25057 }
25058 };
25059
25060 // type check: top level value must be an array
25061 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
25062 {
25063 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
25064 }
25065
25066 // iterate and apply the operations
25067 for (const auto& val : json_patch)
25068 {
25069 // wrapper to get a value for an operation
25070 const auto get_value = [&val](const string_t& op,
25071 const string_t& member,
25072 bool string_type) -> basic_json &
25073 {
25074 // find value
25075 auto it = val.m_data.m_value.object->find(member);
25076
25077 // context-sensitive error message
25078 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
25079
25080 // check if the desired value is present
25081 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
25082 {
25083 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25084 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
25085 }
25086
25087 // check if the result is of type string
25088 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
25089 {
25090 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
25091 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
25092 }
25093
25094 // no error: return value
25095 return it->second;
25096 };
25097
25098 // type check: every element of the array must be an object
25099 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
25100 {
25101 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
25102 }
25103
25104 // collect mandatory members
25105 const auto op = get_value("op", "op", true).template get<string_t>();
25106 const auto path = get_value(op, "path", true).template get<string_t>();
25107 json_pointer ptr(path);
25108
25109 switch (get_op(op))
25110 {
25111 case patch_operations::add:
25112 {
25113 operation_add(ptr, get_value("add", "value", false));
25114 break;
25115 }
25116
25117 case patch_operations::remove:
25118 {
25119 operation_remove(ptr);
25120 break;
25121 }
25122
25123 case patch_operations::replace:
25124 {
25125 // the "path" location must exist - use at()
25126 result.at(ptr) = get_value("replace", "value", false);
25127 break;
25128 }
25129
25130 case patch_operations::move:
25131 {
25132 const auto from_path = get_value("move", "from", true).template get<string_t>();
25133 json_pointer from_ptr(from_path);
25134
25135 // the "from" location must exist - use at()
25136 basic_json const v = result.at(from_ptr);
25137
25138 // The move operation is functionally identical to a
25139 // "remove" operation on the "from" location, followed
25140 // immediately by an "add" operation at the target
25141 // location with the value that was just removed.
25142 operation_remove(from_ptr);
25143 operation_add(ptr, v);
25144 break;
25145 }
25146
25147 case patch_operations::copy:
25148 {
25149 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25150 const json_pointer from_ptr(from_path);
25151
25152 // the "from" location must exist - use at()
25153 basic_json const v = result.at(from_ptr);
25154
25155 // The copy is functionally identical to an "add"
25156 // operation at the target location using the value
25157 // specified in the "from" member.
25158 operation_add(ptr, v);
25159 break;
25160 }
25161
25162 case patch_operations::test:
25163 {
25164 bool success = false;
25165 JSON_TRY
25166 {
25167 // check if "value" matches the one at "path"
25168 // the "path" location must exist - use at()
25169 success = (result.at(ptr) == get_value("test", "value", false));
25170 }
25171 JSON_INTERNAL_CATCH (out_of_range&)
25172 {
25173 // ignore out of range errors: success remains false
25174 }
25175
25176 // throw an exception if the test fails
25177 if (JSON_HEDLEY_UNLIKELY(!success))
25178 {
25179 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25180 }
25181
25182 break;
25183 }
25184
25185 case patch_operations::invalid:
25186 default:
25187 {
25188 // op must be "add", "remove", "replace", "move", "copy", or
25189 // "test"
25190 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25191 }
25192 }
25193 }
25194 }
25195
25198 basic_json patch(const basic_json& json_patch) const
25199 {
25200 basic_json result = *this;
25201 result.patch_inplace(json_patch);
25202 return result;
25203 }
25204
25207 JSON_HEDLEY_WARN_UNUSED_RESULT
25208 static basic_json diff(const basic_json& source, const basic_json& target,
25209 const string_t& path = "")
25210 {
25211 // the patch
25212 basic_json result(value_t::array);
25213
25214 // if the values are the same, return an empty patch
25215 if (source == target)
25216 {
25217 return result;
25218 }
25219
25220 if (source.type() != target.type())
25221 {
25222 // different types: replace value
25223 result.push_back(
25224 {
25225 {"op", "replace"}, {"path", path}, {"value", target}
25226 });
25227 return result;
25228 }
25229
25230 switch (source.type())
25231 {
25232 case value_t::array:
25233 {
25234 // first pass: traverse common elements
25235 std::size_t i = 0;
25236 while (i < source.size() && i < target.size())
25237 {
25238 // recursive call to compare array values at index i
25239 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25240 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25241 ++i;
25242 }
25243
25244 // We now reached the end of at least one array
25245 // in a second pass, traverse the remaining elements
25246
25247 // remove my remaining elements
25248 const auto end_index = static_cast<difference_type>(result.size());
25249 while (i < source.size())
25250 {
25251 // add operations in reverse order to avoid invalid
25252 // indices
25253 result.insert(result.begin() + end_index, object(
25254 {
25255 {"op", "remove"},
25256 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25257 }));
25258 ++i;
25259 }
25260
25261 // add other remaining elements
25262 while (i < target.size())
25263 {
25264 result.push_back(
25265 {
25266 {"op", "add"},
25267 {"path", detail::concat<string_t>(path, "/-")},
25268 {"value", target[i]}
25269 });
25270 ++i;
25271 }
25272
25273 break;
25274 }
25275
25276 case value_t::object:
25277 {
25278 // first pass: traverse this object's elements
25279 for (auto it = source.cbegin(); it != source.cend(); ++it)
25280 {
25281 // escape the key name to be used in a JSON patch
25282 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25283
25284 if (target.find(it.key()) != target.end())
25285 {
25286 // recursive call to compare object values at key it
25287 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25288 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25289 }
25290 else
25291 {
25292 // found a key that is not in o -> remove it
25293 result.push_back(object(
25294 {
25295 {"op", "remove"}, {"path", path_key}
25296 }));
25297 }
25298 }
25299
25300 // second pass: traverse other object's elements
25301 for (auto it = target.cbegin(); it != target.cend(); ++it)
25302 {
25303 if (source.find(it.key()) == source.end())
25304 {
25305 // found a key that is not in this -> add it
25306 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25307 result.push_back(
25308 {
25309 {"op", "add"}, {"path", path_key},
25310 {"value", it.value()}
25311 });
25312 }
25313 }
25314
25315 break;
25316 }
25317
25318 case value_t::null:
25319 case value_t::string:
25320 case value_t::boolean:
25321 case value_t::number_integer:
25322 case value_t::number_unsigned:
25323 case value_t::number_float:
25324 case value_t::binary:
25325 case value_t::discarded:
25326 default:
25327 {
25328 // both primitive types: replace value
25329 result.push_back(
25330 {
25331 {"op", "replace"}, {"path", path}, {"value", target}
25332 });
25333 break;
25334 }
25335 }
25336
25337 return result;
25338 }
25339
25340
25342 // JSON Merge Patch functions //
25344
25347
25350 void merge_patch(const basic_json& apply_patch)
25351 {
25352 if (apply_patch.is_object())
25353 {
25354 if (!is_object())
25355 {
25356 *this = object();
25357 }
25358 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25359 {
25360 if (it.value().is_null())
25361 {
25362 erase(it.key());
25363 }
25364 else
25365 {
25366 operator[](it.key()).merge_patch(it.value());
25367 }
25368 }
25369 }
25370 else
25371 {
25372 *this = apply_patch;
25373 }
25374 }
25375
25377};
25378
25381NLOHMANN_BASIC_JSON_TPL_DECLARATION
25382std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25383{
25384 return j.dump();
25385}
25386
25387inline namespace literals
25388{
25389inline namespace json_literals
25390{
25391
25394JSON_HEDLEY_NON_NULL(1)
25395#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25396 inline nlohmann::json operator""_json(const char* s, std::size_t n)
25397#else
25398 // GCC 4.8 requires a space between "" and suffix
25399 inline nlohmann::json operator"" _json(const char* s, std::size_t n)
25400#endif
25401{
25402 return nlohmann::json::parse(s, s + n);
25403}
25404
25405#if defined(__cpp_char8_t)
25406JSON_HEDLEY_NON_NULL(1)
25407inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
25408{
25409 return nlohmann::json::parse(reinterpret_cast<const char*>(s),
25410 reinterpret_cast<const char*>(s) + n);
25411}
25412#endif
25413
25416JSON_HEDLEY_NON_NULL(1)
25417#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25418 inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
25419#else
25420 // GCC 4.8 requires a space between "" and suffix
25421 inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
25422#endif
25423{
25424 return nlohmann::json::json_pointer(std::string(s, n));
25425}
25426
25427#if defined(__cpp_char8_t)
25428inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
25429{
25430 return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
25431}
25432#endif
25433
25434} // namespace json_literals
25435} // namespace literals
25436NLOHMANN_JSON_NAMESPACE_END
25437
25439// nonmember support //
25441
25442namespace std // NOLINT(cert-dcl58-cpp)
25443{
25444
25447NLOHMANN_BASIC_JSON_TPL_DECLARATION
25448struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25449{
25450 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25451 {
25452 return nlohmann::detail::hash(j);
25453 }
25454};
25455
25456// specialization for std::less<value_t>
25457template<>
25458struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25459{
25464 bool operator()(::nlohmann::detail::value_t lhs,
25465 ::nlohmann::detail::value_t rhs) const noexcept
25466 {
25467#if JSON_HAS_THREE_WAY_COMPARISON
25468 return std::is_lt(lhs <=> rhs); // *NOPAD*
25469#else
25470 return ::nlohmann::detail::operator<(lhs, rhs);
25471#endif
25472 }
25473};
25474
25475// C++20 prohibit function specialization in the std namespace.
25476#ifndef JSON_HAS_CPP_20
25477
25480NLOHMANN_BASIC_JSON_TPL_DECLARATION
25481inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25482 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25483 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25484{
25485 j1.swap(j2);
25486}
25487
25488#endif
25489
25490} // namespace std
25491
25492#if JSON_USE_GLOBAL_UDLS
25493 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25494 using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25495 using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25496 #else
25497 // GCC 4.8 requires a space between "" and suffix
25498 using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25499 using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25500 #endif
25501#endif
25502
25503// #include <nlohmann/detail/macro_unscope.hpp>
25504// __ _____ _____ _____
25505// __| | __| | | | JSON for Modern C++
25506// | | |__ | | | | | | version 3.12.0
25507// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25508//
25509// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
25510// SPDX-License-Identifier: MIT
25511
25512
25513
25514// restore clang diagnostic settings
25515#if defined(__clang__)
25516 #pragma clang diagnostic pop
25517#endif
25518
25519// clean up
25520#undef JSON_ASSERT
25521#undef JSON_INTERNAL_CATCH
25522#undef JSON_THROW
25523#undef JSON_PRIVATE_UNLESS_TESTED
25524#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25525#undef NLOHMANN_BASIC_JSON_TPL
25526#undef JSON_EXPLICIT
25527#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25528#undef JSON_INLINE_VARIABLE
25529#undef JSON_NO_UNIQUE_ADDRESS
25530#undef JSON_DISABLE_ENUM_SERIALIZATION
25531#undef JSON_USE_GLOBAL_UDLS
25532
25533#ifndef JSON_TEST_KEEP_MACROS
25534 #undef JSON_CATCH
25535 #undef JSON_TRY
25536 #undef JSON_HAS_CPP_11
25537 #undef JSON_HAS_CPP_14
25538 #undef JSON_HAS_CPP_17
25539 #undef JSON_HAS_CPP_20
25540 #undef JSON_HAS_CPP_23
25541 #undef JSON_HAS_CPP_26
25542 #undef JSON_HAS_FILESYSTEM
25543 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25544 #undef JSON_HAS_THREE_WAY_COMPARISON
25545 #undef JSON_HAS_RANGES
25546 #undef JSON_HAS_STATIC_RTTI
25547 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25548#endif
25549
25550// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25551// __ _____ _____ _____
25552// __| | __| | | | JSON for Modern C++
25553// | | |__ | | | | | | version 3.12.0
25554// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25555//
25556// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
25557// SPDX-License-Identifier: MIT
25558
25559
25560
25561#undef JSON_HEDLEY_ALWAYS_INLINE
25562#undef JSON_HEDLEY_ARM_VERSION
25563#undef JSON_HEDLEY_ARM_VERSION_CHECK
25564#undef JSON_HEDLEY_ARRAY_PARAM
25565#undef JSON_HEDLEY_ASSUME
25566#undef JSON_HEDLEY_BEGIN_C_DECLS
25567#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25568#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25569#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25570#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25571#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25572#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25573#undef JSON_HEDLEY_CLANG_HAS_WARNING
25574#undef JSON_HEDLEY_COMPCERT_VERSION
25575#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25576#undef JSON_HEDLEY_CONCAT
25577#undef JSON_HEDLEY_CONCAT3
25578#undef JSON_HEDLEY_CONCAT3_EX
25579#undef JSON_HEDLEY_CONCAT_EX
25580#undef JSON_HEDLEY_CONST
25581#undef JSON_HEDLEY_CONSTEXPR
25582#undef JSON_HEDLEY_CONST_CAST
25583#undef JSON_HEDLEY_CPP_CAST
25584#undef JSON_HEDLEY_CRAY_VERSION
25585#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25586#undef JSON_HEDLEY_C_DECL
25587#undef JSON_HEDLEY_DEPRECATED
25588#undef JSON_HEDLEY_DEPRECATED_FOR
25589#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25590#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25591#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25592#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25593#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25594#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25595#undef JSON_HEDLEY_DIAGNOSTIC_POP
25596#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25597#undef JSON_HEDLEY_DMC_VERSION
25598#undef JSON_HEDLEY_DMC_VERSION_CHECK
25599#undef JSON_HEDLEY_EMPTY_BASES
25600#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25601#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25602#undef JSON_HEDLEY_END_C_DECLS
25603#undef JSON_HEDLEY_FLAGS
25604#undef JSON_HEDLEY_FLAGS_CAST
25605#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25606#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25607#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25608#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25609#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25610#undef JSON_HEDLEY_GCC_HAS_FEATURE
25611#undef JSON_HEDLEY_GCC_HAS_WARNING
25612#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25613#undef JSON_HEDLEY_GCC_VERSION
25614#undef JSON_HEDLEY_GCC_VERSION_CHECK
25615#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25616#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25617#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25618#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25619#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25620#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25621#undef JSON_HEDLEY_GNUC_HAS_WARNING
25622#undef JSON_HEDLEY_GNUC_VERSION
25623#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25624#undef JSON_HEDLEY_HAS_ATTRIBUTE
25625#undef JSON_HEDLEY_HAS_BUILTIN
25626#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25627#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25628#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25629#undef JSON_HEDLEY_HAS_EXTENSION
25630#undef JSON_HEDLEY_HAS_FEATURE
25631#undef JSON_HEDLEY_HAS_WARNING
25632#undef JSON_HEDLEY_IAR_VERSION
25633#undef JSON_HEDLEY_IAR_VERSION_CHECK
25634#undef JSON_HEDLEY_IBM_VERSION
25635#undef JSON_HEDLEY_IBM_VERSION_CHECK
25636#undef JSON_HEDLEY_IMPORT
25637#undef JSON_HEDLEY_INLINE
25638#undef JSON_HEDLEY_INTEL_CL_VERSION
25639#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25640#undef JSON_HEDLEY_INTEL_VERSION
25641#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25642#undef JSON_HEDLEY_IS_CONSTANT
25643#undef JSON_HEDLEY_IS_CONSTEXPR_
25644#undef JSON_HEDLEY_LIKELY
25645#undef JSON_HEDLEY_MALLOC
25646#undef JSON_HEDLEY_MCST_LCC_VERSION
25647#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25648#undef JSON_HEDLEY_MESSAGE
25649#undef JSON_HEDLEY_MSVC_VERSION
25650#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25651#undef JSON_HEDLEY_NEVER_INLINE
25652#undef JSON_HEDLEY_NON_NULL
25653#undef JSON_HEDLEY_NO_ESCAPE
25654#undef JSON_HEDLEY_NO_RETURN
25655#undef JSON_HEDLEY_NO_THROW
25656#undef JSON_HEDLEY_NULL
25657#undef JSON_HEDLEY_PELLES_VERSION
25658#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25659#undef JSON_HEDLEY_PGI_VERSION
25660#undef JSON_HEDLEY_PGI_VERSION_CHECK
25661#undef JSON_HEDLEY_PREDICT
25662#undef JSON_HEDLEY_PRINTF_FORMAT
25663#undef JSON_HEDLEY_PRIVATE
25664#undef JSON_HEDLEY_PUBLIC
25665#undef JSON_HEDLEY_PURE
25666#undef JSON_HEDLEY_REINTERPRET_CAST
25667#undef JSON_HEDLEY_REQUIRE
25668#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25669#undef JSON_HEDLEY_REQUIRE_MSG
25670#undef JSON_HEDLEY_RESTRICT
25671#undef JSON_HEDLEY_RETURNS_NON_NULL
25672#undef JSON_HEDLEY_SENTINEL
25673#undef JSON_HEDLEY_STATIC_ASSERT
25674#undef JSON_HEDLEY_STATIC_CAST
25675#undef JSON_HEDLEY_STRINGIFY
25676#undef JSON_HEDLEY_STRINGIFY_EX
25677#undef JSON_HEDLEY_SUNPRO_VERSION
25678#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25679#undef JSON_HEDLEY_TINYC_VERSION
25680#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25681#undef JSON_HEDLEY_TI_ARMCL_VERSION
25682#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25683#undef JSON_HEDLEY_TI_CL2000_VERSION
25684#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25685#undef JSON_HEDLEY_TI_CL430_VERSION
25686#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25687#undef JSON_HEDLEY_TI_CL6X_VERSION
25688#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25689#undef JSON_HEDLEY_TI_CL7X_VERSION
25690#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25691#undef JSON_HEDLEY_TI_CLPRU_VERSION
25692#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25693#undef JSON_HEDLEY_TI_VERSION
25694#undef JSON_HEDLEY_TI_VERSION_CHECK
25695#undef JSON_HEDLEY_UNAVAILABLE
25696#undef JSON_HEDLEY_UNLIKELY
25697#undef JSON_HEDLEY_UNPREDICTABLE
25698#undef JSON_HEDLEY_UNREACHABLE
25699#undef JSON_HEDLEY_UNREACHABLE_RETURN
25700#undef JSON_HEDLEY_VERSION
25701#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25702#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25703#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25704#undef JSON_HEDLEY_VERSION_ENCODE
25705#undef JSON_HEDLEY_WARNING
25706#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25707#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25708#undef JSON_HEDLEY_FALL_THROUGH
25709
25710
25711
25712#endif // INCLUDE_NLOHMANN_JSON_HPP_
a class to store JSON values
Definition json.hpp:20219
constexpr bool is_string() const noexcept
Definition json.hpp:21518
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22753
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:20293
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22319
size_type size() const noexcept
Definition json.hpp:23094
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24606
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
Definition json.hpp:21891
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22951
reference back()
access the last element
Definition json.hpp:22557
basic_json value_type
Definition json.hpp:20330
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20958
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22967
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25198
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
Definition json.hpp:24365
const_reference front() const
access the first element
Definition json.hpp:22550
constexpr bool is_array() const noexcept
Definition json.hpp:21511
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
Definition json.hpp:23612
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22500
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22870
iter_impl< const basic_json > const_iterator
Definition json.hpp:20353
constexpr bool is_number_integer() const noexcept
Definition json.hpp:21483
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:20357
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24801
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24846
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:20348
std::size_t size_type
Definition json.hpp:20340
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21455
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22343
detail::error_handler_t error_handler_t
Definition json.hpp:20291
const value_type & const_reference
Definition json.hpp:20335
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23689
ReferenceType get_ref()
Definition json.hpp:21981
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23133
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23558
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21992
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21532
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23349
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23237
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22288
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23039
basic_json & operator=(basic_json other) noexcept(//NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator)std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:21372
const_reference back() const
access the last element
Definition json.hpp:22566
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22648
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23294
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:23629
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24702
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21100
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23461
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24786
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20363
nlohmann::byte_container_with_subtype< std::vector< std::uint8_t > > binary_t
Definition json.hpp:20488
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22151
iterator end() noexcept
Definition json.hpp:22942
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21490
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23565
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24565
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22974
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23333
detail::parser_callback_t< basic_json > parser_callback_t
Definition json.hpp:20925
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21141
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24501
iterator begin() noexcept
Definition json.hpp:22917
detail::parse_event_t parse_event_t
Definition json.hpp:20921
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22398
const_iterator cend() const noexcept
Definition json.hpp:22958
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24756
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24888
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21111
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20946
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24590
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24902
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24717
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22764
std::vector< basic_json, std::allocator< basic_json > > array_t
Definition json.hpp:20464
nlohmann::ordered_map< std::string, basic_json, default_object_comparator_t, std::allocator< std::pair< const std::string, basic_json > > > object_t
Definition json.hpp:20456
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22063
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23481
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24927
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22451
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24860
value_type & reference
Definition json.hpp:20333
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:20297
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22887
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24471
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24581
iterator find(const typename object_t::key_type &key)
Definition json.hpp:22800
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:21089
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24535
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22189
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20371
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21148
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22814
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24462
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22578
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23434
double number_float_t
Definition json.hpp:20484
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22373
std::allocator< basic_json > allocator_type
Definition json.hpp:20343
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:20346
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:21419
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25350
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21945
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24547
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22085
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22830
constexpr bool is_number_float() const noexcept
Definition json.hpp:21497
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22981
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24508
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24874
bool boolean_t
Definition json.hpp:20472
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const string_t &path="")
creates a diff as a JSON patch
Definition json.hpp:25208
std::less< std::string > default_object_comparator_t
Definition json.hpp:20451
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23325
const_iterator cbegin() const noexcept
Definition json.hpp:22933
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22266
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21703
~basic_json() noexcept
destructor
Definition json.hpp:21401
const_reverse_iterator crend() const noexcept
Definition json.hpp:23002
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:21030
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23705
binary_t & get_binary()
get a binary value
Definition json.hpp:22051
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22926
constexpr bool is_number() const noexcept
Definition json.hpp:21476
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23532
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24648
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21932
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22207
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
Definition json.hpp:23014
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24527
std::int64_t number_integer_t
Definition json.hpp:20476
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21692
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22169
constexpr bool is_binary() const noexcept
Definition json.hpp:21525
void swap(object_t &other)
exchanges the values
Definition json.hpp:23657
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24911
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23512
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24556
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21122
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:23032
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23055
void swap(array_t &other)
exchanges the values
Definition json.hpp:23641
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22771
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23262
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22894
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21441
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23358
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22474
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21133
detail::bjdata_version_t bjdata_version_t
Definition json.hpp:20295
std::string string_t
Definition json.hpp:20468
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23270
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22424
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22131
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24771
json_value m_value
the value of the current element
Definition json.hpp:24403
const_reverse_iterator crbegin() const noexcept
Definition json.hpp:22995
json_sax< basic_json > json_sax_t
Definition json.hpp:20301
constexpr bool is_boolean() const noexcept
Definition json.hpp:21469
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22860
reference front()
access the first element
Definition json.hpp:22543
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21448
constexpr bool is_null() const noexcept
Definition json.hpp:21462
void clear() noexcept
clears the contents
Definition json.hpp:23176
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24519
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21346
iter_impl< basic_json > iterator
Definition json.hpp:20351
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20938
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22253
std::ptrdiff_t difference_type
Definition json.hpp:20338
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23454
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22988
std::uint64_t number_unsigned_t
Definition json.hpp:20480
friend std::istream & operator>>(std::istream &i, basic_json &j)
Definition json.hpp:24350
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24485
void swap(string_t &other)
exchanges the values
Definition json.hpp:23673
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20972
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:20355
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22108
detail::actual_object_comparator_t< basic_json > object_comparator_t
Definition json.hpp:20492
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21273
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23302
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23383
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24478
constexpr bool is_object() const noexcept
Definition json.hpp:21504
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24494
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24663
iterator insert_iterator(const_iterator pos, Args &&... args)
Helper for insertion of an iterator.
Definition json.hpp:23415
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21160
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22878
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24574
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22846
::nlohmann::json_pointer< std::string > json_pointer
Definition json.hpp:20287
an internal type for a backed binary type
Definition json.hpp:6255
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6261
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6283
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6271
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6310
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6276
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6317
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6266
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6302
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6324
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9908
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9924
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9945
void write_bson(const BasicJsonType &j)
Definition json.hpp:15899
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false, const bjdata_version_t bjdata_version=bjdata_version_t::draft2)
Definition json.hpp:16579
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15890
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16252
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15928
general exception of the basic_json class
Definition json.hpp:4556
const int id
the id of the exception
Definition json.hpp:4565
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4559
Definition json.hpp:6558
Definition json.hpp:6603
exception indicating errors with iterators
Definition json.hpp:4725
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14281
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13835
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14226
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13825
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14168
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14208
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14272
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14078
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14381
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14119
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:14016
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14235
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14343
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
Definition json.hpp:13730
pointer operator->() const
dereference the iterator
Definition json.hpp:13974
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14314
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14292
reference value() const
return the value of an iterator
Definition json.hpp:14397
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14217
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:14027
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13930
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14303
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
Definition json.hpp:13734
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13810
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14159
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14067
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13800
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13891
Definition json.hpp:5517
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5582
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5588
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5565
const iteration_proxy_value & operator*() const
dereference operator (needed for range-based for)
Definition json.hpp:5559
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5630
const string_type & key() const
return key of the iterator
Definition json.hpp:5594
proxy class for the items() function
Definition json.hpp:5638
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5663
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5657
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5647
Definition json.hpp:6669
Definition json.hpp:15611
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14476
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14488
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14482
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14500
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14524
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14530
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14518
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14466
reference value() const
return the value of an iterator
Definition json.hpp:14537
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14473
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14494
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14464
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14512
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14469
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14506
Definition json.hpp:9623
Definition json.hpp:9186
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8880
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8894
Definition json.hpp:7120
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7147
token_type
token types for the parser
Definition json.hpp:7124
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:7132
@ begin_array
the character for array begin [
Definition json.hpp:7133
@ value_string
a string – use get_string() for actual value
Definition json.hpp:7129
@ end_array
the character for array end ]
Definition json.hpp:7135
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:7125
@ parse_error
indicating a parse error
Definition json.hpp:7139
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:7131
@ value_separator
the value separator ,
Definition json.hpp:7138
@ end_object
the character for object end }
Definition json.hpp:7136
@ literal_true
the true literal
Definition json.hpp:7126
@ begin_object
the character for object begin {
Definition json.hpp:7134
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:7130
@ literal_null
the null literal
Definition json.hpp:7128
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:7140
@ name_separator
the name separator :
Definition json.hpp:7137
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:7141
@ literal_false
the false literal
Definition json.hpp:7127
lexical analysis
Definition json.hpp:7197
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8579
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8566
std::string get_token_string() const
return the last read token (for errors only).
Definition json.hpp:8541
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8500
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8533
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8506
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8518
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8512
exception indicating other library errors
Definition json.hpp:4777
exception indicating access out of the defined range
Definition json.hpp:4760
Definition json.hpp:15830
output adapter for output streams
Definition json.hpp:15782
output adapter for basic_string
Definition json.hpp:15807
output adapter for byte vectors
Definition json.hpp:15757
exception indicating a parse error
Definition json.hpp:4672
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4684
const std::size_t byte
byte index of the parse error
Definition json.hpp:4709
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:13028
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:13088
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool ignore_comments=false, const bool ignore_trailing_commas_=false)
a parser reading from an input adapter
Definition json.hpp:13004
Definition json.hpp:13515
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13544
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13538
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13550
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13532
Definition json.hpp:18878
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:19802
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18893
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:19797
const char decimal_point
the locale's decimal point character
Definition json.hpp:19799
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19810
string_t indent_string
the indentation string
Definition json.hpp:19807
const std::lconv * loc
the locale
Definition json.hpp:19795
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:19792
const char indent_char
the indentation character
Definition json.hpp:19805
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18933
exception indicating executing a member function with a wrong type
Definition json.hpp:4743
Definition json.hpp:6848
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14632
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:14727
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:14734
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:15527
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14658
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14793
void pop_back()
remove last reference token
Definition json.hpp:14755
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14664
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14712
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14786
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.hpp:15577
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14694
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:14719
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14741
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14704
const string_t & back() const
return last reference token
Definition json.hpp:14767
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:15552
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14685
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14779
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:17770
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18217
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:18053
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17914
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18553
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18312
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18653
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:18705
Definition json.hpp:17901
Definition json.hpp:18040
detail namespace with internal helper functions
Definition json.hpp:260
input_format_t
the supported input formats
Definition json.hpp:6546
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13635
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:18790
parse_event_t
Definition json.hpp:12968
@ value
the parser finished reading a JSON value
Definition json.hpp:12980
@ key
the parser read a key of a value in an object
Definition json.hpp:12978
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:12976
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:12974
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:12970
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:12972
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15752
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3102
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9894
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9881
@ ignore
ignore tags
Definition json.hpp:9883
@ store
store tags as binary type
Definition json.hpp:9884
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:9882
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13637
value_t
the JSON type enumeration
Definition json.hpp:3004
@ null
null value
Definition json.hpp:3005
@ number_integer
number value (signed integer)
Definition json.hpp:3010
@ boolean
boolean value
Definition json.hpp:3009
@ discarded
discarded by the parser callback function
Definition json.hpp:3014
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3013
@ object
object (unordered set of name/value pairs)
Definition json.hpp:3006
@ string
string value
Definition json.hpp:3008
@ number_float
number value (floating-point)
Definition json.hpp:3012
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3011
@ array
array (ordered collection of values)
Definition json.hpp:3007
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6386
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3136
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3033
error_handler_t
how to treat decoding errors
Definition json.hpp:18870
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:18871
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:18872
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:13633
bjdata_version_t
how to encode BJData
Definition json.hpp:15865
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3121
Definition json.hpp:3721
Definition json.hpp:292
Definition json.hpp:5748
Definition json.hpp:4821
an iterator value
Definition json.hpp:13631
Definition json.hpp:3424
Definition json.hpp:3405
Default base class of the basic_json class.
Definition json.hpp:14579
Definition json.hpp:263
Definition json.hpp:3337
Definition json.hpp:4301
Definition json.hpp:4255
Definition json.hpp:6723
namespace for Niels Lohmann
Definition json.hpp:6197
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:6221
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:6211
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:6201
Definition json.hpp:3738
Definition json.hpp:3817
Definition json.hpp:17783
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17807
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17889
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17872
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17795
Definition json.hpp:5391
Definition json.hpp:3660
Definition json.hpp:3716
Definition json.hpp:3685
Definition json.hpp:3700
Definition json.hpp:3254
Definition json.hpp:3609
Definition json.hpp:3596
Definition json.hpp:4353
Definition json.hpp:4144
Definition json.hpp:4017
Definition json.hpp:4088
Definition json.hpp:3938
Definition json.hpp:3975
Definition json.hpp:4091
Definition json.hpp:4104
Definition json.hpp:3911
Definition json.hpp:4061
Definition json.hpp:3971
Definition json.hpp:3982
Definition json.hpp:4107
Definition json.hpp:3849
Definition json.hpp:3830
Definition json.hpp:308
Definition json.hpp:3668
Definition json.hpp:6912
Definition json.hpp:3864
Definition json.hpp:4113
Definition json.hpp:4134
Definition json.hpp:3619
Definition json.hpp:4206
Definition json.hpp:4210
Definition json.hpp:3883
Definition json.hpp:9813
Definition json.hpp:9782
Definition json.hpp:4124
Definition json.hpp:4375
Definition json.hpp:3824
Definition json.hpp:278
struct to capture the start position of the current token
Definition json.hpp:3167
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3171
std::size_t lines_read
the number of lines read
Definition json.hpp:3173
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3169
Definition json.hpp:3343
Definition json.hpp:6164
Definition json.hpp:3274
Definition json.hpp:3293
SAX interface.
Definition json.hpp:8745
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19852
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25464